You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by co...@apache.org on 2018/04/30 16:35:37 UTC

[1/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.

Repository: sentry
Updated Branches:
  refs/heads/master 0668237aa -> 6752f14aa


http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSqoop.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSqoop.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSqoop.java
new file mode 100644
index 0000000..91b173d
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSqoop.java
@@ -0,0 +1,531 @@
+/**
+ * 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.sentry.cli.tools;
+
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.common.AuthorizationComponent;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+public class TestSentryShellSqoop extends SentryGenericServiceIntegrationBase {
+  private File confDir;
+  private File confPath;
+  private static String TEST_ROLE_NAME_1 = "testRole1";
+  private static String TEST_ROLE_NAME_2 = "testRole2";
+  private String requestorName = "";
+  private String service = "sqoopServer1";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();//.getProperty("user.name", "");
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+  }
+
+  @Test
+  public void testCreateDropRole() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: create role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+        // test: create role with --create_role
+        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+
+        // validate the result, list roles with -lr
+        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // validate the result, list roles with --list_role
+        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // test: drop role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+        // test: drop role with --drop_role
+        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listAllRoles(requestorName, AuthorizationComponent.SQOOP);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+      }
+    });
+  }
+
+  @Test
+  public void testAddDeleteRoleForGroup() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // Group names are case sensitive - mixed case names should work
+        String TEST_GROUP_1 = "testGroup1";
+        String TEST_GROUP_2 = "testGroup2";
+        String TEST_GROUP_3 = "testGroup3";
+
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+        client.createRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
+        // test: add role to group with -arg
+        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+        // test: add role to multiple groups
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+            "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+        // test: add role to group with --add_role_group
+        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+            "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+
+        // validate the result list roles with -lr and -g
+        args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // list roles with --list_role and -g
+        args = new String[] { "--list_role", "-g", TEST_GROUP_2, "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // List the groups and roles via listGroups
+        args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true);
+        assertEquals(3, groups.size());
+        assertTrue(groups.contains("testGroup3 = testrole1"));
+        assertTrue(groups.contains("testGroup2 = testrole1"));
+        assertTrue(groups.contains("testGroup1 = testrole2, testrole1"));
+
+        // test: delete role from group with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+        // test: delete role to multiple groups
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+            "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+        // test: delete role from group with --delete_role_group
+        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+            "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, AuthorizationComponent.SQOOP);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, AuthorizationComponent.SQOOP);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, AuthorizationComponent.SQOOP);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
+      }
+    });
+  }
+
+  @Test
+  public void testCaseSensitiveGroupName() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+        // add role to a group (lower case)
+        String[] args = {"-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop"};
+        SentryShellGeneric.main(args);
+
+        // validate the roles when group name is same case as above
+        args = new String[]{"-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop"};
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // roles should be empty when group name is different case than above
+        args = new String[]{"-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop"};
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames);
+      }
+    });
+  }
+
+  public static String grant(boolean shortOption) {
+    return shortOption ? "-gpr" : "--grant_privilege_role";
+  }
+
+  public static String revoke(boolean shortOption) {
+    return shortOption ? "-rpr" : "--revoke_privilege_role";
+  }
+
+  public static String list(boolean shortOption) {
+    return shortOption ? "-lp" : "--list_privilege";
+  }
+
+  private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+        client.createRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
+
+        String [] privs = {
+            "SERVER=sqoopserver1->CONNECTOR=c1->action=read",
+            "SERVER=sqoopserver1->JOB=j1->action=write",
+            "SERVER=sqoopserver1->LINK=l1->action=read",
+        };
+        for (int i = 0; i < privs.length; ++i) {
+          // test: grant privilege to role
+          String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+            privs[ i ],
+            "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+          SentryShellGeneric.main(args);
+        }
+
+        // test the list privilege
+        String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+
+        assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
+        for (int i = 0; i < privs.length; ++i) {
+          assertTrue("Expected privilege: " + privs[i] + " in " + Arrays.toString(privilegeStrs.toArray()), privilegeStrs.contains(privs[i]));
+        }
+
+        for (int i = 0; i < privs.length; ++i) {
+          args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+            privs[ i ], "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+          SentryShellGeneric.main(args);
+          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+            TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP, service);
+          assertEquals("Incorrect number of privileges. Received privileges: " + Arrays.toString(privileges.toArray()), privs.length - (i + 1), privileges.size());
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
+      }
+    });
+  }
+
+
+  @Test
+  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+    assertGrantRevokePrivilege(true);
+  }
+
+  @Test
+  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+    assertGrantRevokePrivilege(false);
+  }
+
+  @Test
+  public void testNegativeCaseWithInvalidArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+        // test: create duplicate role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for creating duplicate role");
+        } catch (SentryUserException e) {
+          // expected exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // test: drop non-exist role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for dropping non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // test: add non-exist role to group with -arg
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for granting non-exist role to group");
+        } catch (SentryUserException e) {
+          // excepted exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // test: drop group from non-exist role with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for drop group from non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // test: grant privilege to role with the error privilege format
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=all",
+            "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // excepted exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+      }
+    });
+  }
+
+  @Test
+  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String strOptionConf = "conf";
+        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+        // test: the conf is required argument
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "sqoop" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
+
+        // test: -r is required when create role
+        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when drop role
+        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when add role to group
+        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when add role to group
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when delete role from group
+        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when delete role from group
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when grant privilege to role
+        args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when grant privilege to role
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: action is required in privilege
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "Server=sqoopServer1->Connector", "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+         try {
+          getShellResultWithOSRedirect(sentryShell, args, false);
+          fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+           // expected
+        } catch (Exception e) {
+           fail ("Unexpected exception received. " + e);
+         }
+
+        // test: -r is required when revoke privilege from role
+        args = new String[] { "-rpr", "-p", "Server=sqoopServer1->Connector->action=*", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when revoke privilege from role
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: command option is required for shell
+        args = new String[] {"-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsgsContains(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
+                "-arg Add role to group",
+                "-cr Create role",
+                "-rpr Revoke privilege from role",
+                "-drg Delete role from group",
+                "-lr List role",
+                "-lp List privilege",
+                "-gpr Grant privilege to role",
+                "-dr Drop role");
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
+      }
+    });
+  }
+
+  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+  private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
+      String[] args, boolean expectedExecuteResult) throws Exception {
+    PrintStream oldOut = System.out;
+    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+    System.setOut(new PrintStream(outContent));
+    assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
+    Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n"));
+    System.setOut(oldOut);
+    return resultSet;
+  }
+
+  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
+    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
+      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
+          expectedRoleNames.length, roleNames.size());
+      Set<String> lowerCaseRoles = new HashSet<String>();
+      for (String role : roleNames) {
+        lowerCaseRoles.add(role.toLowerCase());
+      }
+
+      for (String expectedRole : expectedRoleNames) {
+        assertTrue("Expected role: " + expectedRole,
+            lowerCaseRoles.contains(expectedRole.toLowerCase()));
+      }
+    }
+  }
+
+  private void validateMissingParameterMsg(SentryShellGeneric sentryShell, String[] args,
+      String expectedErrorMsg) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
+  }
+
+  private void validateMissingParameterMsgsContains(SentryShellGeneric sentryShell, String[] args,
+      String ... expectedErrorMsgsContains) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    boolean foundAllMessages = false;
+    Iterator<String> it = errorMsgs.iterator();
+    while (it.hasNext()) {
+      String errorMessage = it.next();
+      boolean missingExpected = false;
+      for (String expectedContains : expectedErrorMsgsContains) {
+        if (!errorMessage.contains(expectedContains)) {
+          missingExpected = true;
+          break;
+        }
+      }
+      if (!missingExpected) {
+        foundAllMessages = true;
+        break;
+      }
+    }
+    assertTrue(foundAllMessages);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/cacerts.jks
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/cacerts.jks b/sentry-tools/src/test/resources/cacerts.jks
new file mode 100644
index 0000000..6ac6495
Binary files /dev/null and b/sentry-tools/src/test/resources/cacerts.jks differ

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/indexer_case.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/indexer_case.ini b/sentry-tools/src/test/resources/indexer_case.ini
new file mode 100644
index 0000000..f1afe1f
--- /dev/null
+++ b/sentry-tools/src/test/resources/indexer_case.ini
@@ -0,0 +1,26 @@
+# 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.
+
+[groups]
+groupa = RoLe1
+groupb = rOlE1
+groupc = ROLE2
+
+[roles]
+RoLe1 = indexer=*
+rOlE1 = indexer=*
+ROLE2 = indexer=*

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/indexer_config_import_tool.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/indexer_config_import_tool.ini b/sentry-tools/src/test/resources/indexer_config_import_tool.ini
new file mode 100644
index 0000000..c1bfe4b
--- /dev/null
+++ b/sentry-tools/src/test/resources/indexer_config_import_tool.ini
@@ -0,0 +1,29 @@
+# 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.
+
+[groups]
+corporal = corporal_role
+sergeant = corporal_role, sergeant_role
+general = corporal_role, sergeant_role, general_role
+commander_in_chief = corporal_role, sergeant_role, general_role, commander_in_chief_role
+
+[roles]
+corporal_role = indexer=info->action=read, \
+  indexer=info->action=write
+sergeant_role = indexer=info->action=write
+general_role = indexer=info->action=*
+commander_in_chief_role = indexer=*

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/indexer_invalid.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/indexer_invalid.ini b/sentry-tools/src/test/resources/indexer_invalid.ini
new file mode 100644
index 0000000..03083a7
--- /dev/null
+++ b/sentry-tools/src/test/resources/indexer_invalid.ini
@@ -0,0 +1,21 @@
+# 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.
+
+[groups]
+
+[roles]
+

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/keystore.jks
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/keystore.jks b/sentry-tools/src/test/resources/keystore.jks
new file mode 100644
index 0000000..a6beece
Binary files /dev/null and b/sentry-tools/src/test/resources/keystore.jks differ

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/log4j.properties b/sentry-tools/src/test/resources/log4j.properties
new file mode 100644
index 0000000..9766758
--- /dev/null
+++ b/sentry-tools/src/test/resources/log4j.properties
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+
+# Define some default values that can be overridden by system properties.
+#
+# For testing, it may also be convenient to specify
+
+log4j.rootLogger=DEBUG,console
+
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d (%t) [%p - %l] %m%n
+
+log4j.logger.org.apache.hadoop.conf.Configuration=INFO
+log4j.logger.org.apache.hadoop.metrics2=INFO
+log4j.logger.org.apache.directory=INFO
+log4j.logger.org.apache.directory.api.ldap.model.entry.AbstractValue=WARN

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/solr_case.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/solr_case.ini b/sentry-tools/src/test/resources/solr_case.ini
new file mode 100644
index 0000000..fbbebfc
--- /dev/null
+++ b/sentry-tools/src/test/resources/solr_case.ini
@@ -0,0 +1,26 @@
+# 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.
+
+[groups]
+groupa = RoLe1
+groupb = rOlE1
+groupc = ROLE2
+
+[roles]
+RoLe1 = collection=*
+rOlE1 = collection=*
+ROLE2 = collection=*

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/solr_config_import_tool.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/solr_config_import_tool.ini b/sentry-tools/src/test/resources/solr_config_import_tool.ini
new file mode 100644
index 0000000..da7df4c
--- /dev/null
+++ b/sentry-tools/src/test/resources/solr_config_import_tool.ini
@@ -0,0 +1,29 @@
+# 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.
+
+[groups]
+corporal = corporal_role
+sergeant = corporal_role, sergeant_role
+general = corporal_role, sergeant_role, general_role
+commander_in_chief = corporal_role, sergeant_role, general_role, commander_in_chief_role
+
+[roles]
+corporal_role = collection=info->action=query, \
+  collection=info->action=update
+sergeant_role = collection=info->action=update
+general_role = collection=info->action=*
+commander_in_chief_role = collection=*

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/resources/solr_invalid.ini
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/resources/solr_invalid.ini b/sentry-tools/src/test/resources/solr_invalid.ini
new file mode 100644
index 0000000..03083a7
--- /dev/null
+++ b/sentry-tools/src/test/resources/solr_invalid.ini
@@ -0,0 +1,21 @@
+# 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.
+
+[groups]
+
+[roles]
+


[4/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.

Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaTool.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaTool.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaTool.java
new file mode 100644
index 0000000..893f80b
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaTool.java
@@ -0,0 +1,595 @@
+/**
+ * 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.sentry.cli.tools;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.MalformedURLException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.IllegalFormatException;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.io.output.NullOutputStream;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hive.beeline.BeeLine;
+import org.apache.sentry.Command;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.core.common.exception.SentrySiteConfigurationException;
+import org.apache.sentry.provider.db.service.persistent.SentryStoreSchemaInfo;
+import org.apache.sentry.cli.tools.SentrySchemaHelper.NestedScriptParser;
+import org.apache.sentry.service.thrift.SentryService;
+import org.apache.sentry.service.thrift.ServiceConstants;
+
+public class SentrySchemaTool {
+  private static final String SENTRY_SCRIP_DIR = File.separatorChar + "scripts"
+      + File.separatorChar + "sentrystore" + File.separatorChar + "upgrade";
+  private String userName = null;
+  private String passWord = null;
+  private String connectionURL = null;
+  private String driver = null;
+  private boolean dryRun = false;
+  private String dbOpts = null;
+  private boolean verbose = false;
+  private final Configuration sentryConf;
+  private final String dbType;
+  private final SentryStoreSchemaInfo sentryStoreSchemaInfo;
+
+  public SentrySchemaTool(Configuration sentryConf, String dbType)
+      throws SentryUserException, IOException {
+    this(System.getenv("SENTRY_HOME") + SENTRY_SCRIP_DIR, sentryConf, dbType);
+  }
+
+  public SentrySchemaTool(String sentryScripPath, Configuration sentryConf,
+      String dbType) throws SentryUserException, IOException {
+    if (sentryScripPath == null || sentryScripPath.isEmpty()) {
+      throw new SentryUserException("No Sentry script dir provided");
+    }
+    this.sentryConf = sentryConf;
+    this.dbType = dbType;
+    this.sentryStoreSchemaInfo = new SentryStoreSchemaInfo(sentryScripPath,
+        dbType);
+    userName = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER,
+        ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER_DEFAULT);
+    //Password will be read from Credential provider specified using property
+    // CREDENTIAL_PROVIDER_PATH("hadoop.security.credential.provider.path" in sentry-site.xml
+    // it falls back to reading directly from sentry-site.xml
+    char[] passTmp = sentryConf.getPassword(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
+    if(passTmp != null) {
+      passWord = new String(passTmp);
+    } else {
+      throw new SentrySiteConfigurationException("Error reading " + ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
+    }
+
+    try {
+      connectionURL = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_URL);
+      if(dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)) {
+        driver = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER,
+            ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER_DEFAULT);
+      } else {
+        driver = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER);
+      }
+      // load required JDBC driver
+      Class.forName(driver);
+    } catch (IOException e) {
+      throw new SentryUserException("Missing property: " + e.getMessage());
+    } catch (ClassNotFoundException e) {
+      throw new SentryUserException("Failed to load driver", e);
+    }
+  }
+
+  public Configuration getConfiguration() {
+    return sentryConf;
+  }
+
+  public void setUserName(String userName) {
+    this.userName = userName;
+  }
+
+  public void setPassWord(String passWord) {
+    this.passWord = passWord;
+  }
+
+  public void setDryRun(boolean dryRun) {
+    this.dryRun = dryRun;
+  }
+
+  public void setVerbose(boolean verbose) {
+    this.verbose = verbose;
+  }
+
+  public String getDbOpts() {
+    return dbOpts;
+  }
+
+  public void setDbOpts(String dbOpts) {
+    this.dbOpts = dbOpts;
+  }
+
+  private static void printAndExit(Options cmdLineOptions) {
+    HelpFormatter formatter = new HelpFormatter();
+    formatter.printHelp("schemaTool", cmdLineOptions);
+    System.exit(1);
+  }
+
+  /***
+   * Print Hive version and schema version
+   * @throws SentryUserException
+   */
+  public void showInfo() throws SentryUserException {
+    Connection sentryStoreConn = getConnectionToMetastore(true);
+    System.out.println("Sentry distribution version:\t "
+        + SentryStoreSchemaInfo.getSentryVersion());
+    System.out.println("SentryStore schema version:\t "
+        + getMetaStoreSchemaVersion(sentryStoreConn));
+  }
+
+  // read schema version from sentry store
+  private String getMetaStoreSchemaVersion(Connection sentryStoreConn)
+      throws SentryUserException {
+    String versionQuery;
+    if (SentrySchemaHelper.getDbCommandParser(dbType).needsQuotedIdentifier()) {
+      versionQuery = "select t.\"SCHEMA_VERSION\" from \"SENTRY_VERSION\" t";
+    } else {
+      versionQuery = "select t.SCHEMA_VERSION from SENTRY_VERSION t";
+    }
+    try (Statement stmt = sentryStoreConn.createStatement();
+      ResultSet res = stmt.executeQuery(versionQuery)) {
+      if (!res.next()) {
+        throw new SentryUserException("Didn't find version data in sentry store");
+      }
+      String currentSchemaVersion = res.getString(1);
+      sentryStoreConn.close();
+      return currentSchemaVersion;
+    } catch (SQLException e) {
+      throw new SentryUserException("Failed to get schema version.", e);
+    }
+  }
+
+  // test the connection sentry store using the config property
+  private void testConnectionToMetastore() throws SentryUserException {
+    try (Connection conn = getConnectionToMetastore(true)) {
+      conn.close();
+    } catch (SQLException e) {
+      throw new SentryUserException("Failed to close sentry store connection", e);
+    }
+  }
+
+  /***
+   * get JDBC connection to sentry store db
+   *
+   * @param printInfo print connection parameters
+   * @return
+   * @throws SentryUserException
+   */
+  private Connection getConnectionToMetastore(boolean printInfo)
+      throws SentryUserException {
+    if (printInfo) {
+      System.out.println("Sentry store connection URL:\t " + connectionURL);
+      System.out.println("Sentry store Connection Driver :\t " + driver);
+      System.out.println("Sentry store connection User:\t " + userName);
+    }
+    if (userName == null || userName.isEmpty()) {
+      throw new SentryUserException("UserName empty ");
+    }
+    try {
+      // Connect using the JDBC URL and user/pass from conf
+      return DriverManager.getConnection(connectionURL, userName, passWord);
+    } catch (SQLException e) {
+      throw new SentryUserException("Failed to make connection to Sentry store.", e);
+    }
+  }
+
+  /**
+   * check if the current schema version in sentry store matches the Hive version
+   * @throws SentryUserException
+   */
+  public void verifySchemaVersion() throws SentryUserException {
+    // don't check version if its a dry run
+    if (dryRun) {
+      return;
+    }
+    String newSchemaVersion =
+        getMetaStoreSchemaVersion(getConnectionToMetastore(false));
+    // verify that the new version is added to schema
+    if (!sentryStoreSchemaInfo.getSentrySchemaVersion().equalsIgnoreCase(
+        newSchemaVersion)) {
+      throw new SentryUserException("Found unexpected schema version "
+          + newSchemaVersion);
+    }
+  }
+
+  /**
+   * Perform sentry store schema upgrade. extract the current schema version from sentry store
+   * @throws SentryUserException
+   */
+  public void doUpgrade() throws SentryUserException {
+    String fromVersion = getMetaStoreSchemaVersion(getConnectionToMetastore(false));
+    if (fromVersion == null || fromVersion.isEmpty()) {
+      throw new SentryUserException(
+          "Schema version not stored in the sentry store. "
+              +
+          "Metastore schema is too old or corrupt. Try specifying the version manually");
+    }
+    doUpgrade(fromVersion);
+  }
+
+  /**
+   * Perform sentry store schema upgrade
+   *
+   * @param fromSchemaVer
+   *          Existing version of the sentry store. If null, then read from the sentry store
+   * @throws SentryUserException
+   */
+  public void doUpgrade(String fromSchemaVer) throws SentryUserException {
+    if (sentryStoreSchemaInfo.getSentrySchemaVersion().equals(fromSchemaVer)) {
+      System.out.println("No schema upgrade required from version " + fromSchemaVer);
+      return;
+    }
+    // Find the list of scripts to execute for this upgrade
+    List<String> upgradeScripts =
+        sentryStoreSchemaInfo.getUpgradeScripts(fromSchemaVer);
+    testConnectionToMetastore();
+    System.out.println("Starting upgrade sentry store schema from version " +
+ fromSchemaVer + " to "
+        + sentryStoreSchemaInfo.getSentrySchemaVersion());
+    String scriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
+    try {
+      for (String scriptFile : upgradeScripts) {
+        System.out.println("Upgrade script " + scriptFile);
+        if (!dryRun) {
+          runBeeLine(scriptDir, scriptFile);
+          System.out.println("Completed " + scriptFile);
+        }
+      }
+    } catch (IOException eIO) {
+      throw new SentryUserException(
+          "Upgrade FAILED! Metastore state would be inconsistent !!", eIO);
+    }
+
+    // Revalidated the new version after upgrade
+    verifySchemaVersion();
+  }
+
+  /**
+   * Initialize the sentry store schema to current version
+   *
+   * @throws SentryUserException
+   */
+  public void doInit() throws SentryUserException {
+    doInit(sentryStoreSchemaInfo.getSentrySchemaVersion());
+
+    // Revalidated the new version after upgrade
+    verifySchemaVersion();
+  }
+
+  /**
+   * Initialize the sentry store schema
+   *
+   * @param toVersion
+   *          If null then current hive version is used
+   * @throws SentryUserException
+   */
+  public void doInit(String toVersion) throws SentryUserException {
+    testConnectionToMetastore();
+    System.out.println("Starting sentry store schema initialization to " + toVersion);
+
+    String initScriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
+    String initScriptFile = sentryStoreSchemaInfo.generateInitFileName(toVersion);
+
+    try {
+      System.out.println("Initialization script " + initScriptFile);
+      if (!dryRun) {
+        runBeeLine(initScriptDir, initScriptFile);
+        System.out.println("Initialization script completed");
+      }
+    } catch (IOException e) {
+      throw new SentryUserException("Schema initialization FAILED!"
+          + " Metastore state would be inconsistent !!", e);
+    }
+  }
+
+  // Flatten the nested upgrade script into a buffer
+  public static String buildCommand(NestedScriptParser dbCommandParser,
+        String scriptDir, String scriptFile) throws IllegalFormatException, IOException {
+
+    BufferedReader bfReader =
+        new BufferedReader(new FileReader(scriptDir + File.separatorChar + scriptFile));
+    String currLine;
+    StringBuilder sb = new StringBuilder();
+    String currentCommand = null;
+    while ((currLine = bfReader.readLine()) != null) {
+      currLine = currLine.trim();
+      if (currLine.isEmpty()) {
+        continue; // skip empty lines
+      }
+
+      if (currentCommand == null) {
+        currentCommand = currLine;
+      } else {
+        currentCommand = currentCommand + " " + currLine;
+      }
+      if (dbCommandParser.isPartialCommand(currLine)) {
+        // if its a partial line, continue collecting the pieces
+        continue;
+      }
+
+      // if this is a valid executable command then add it to the buffer
+      if (!dbCommandParser.isNonExecCommand(currentCommand)) {
+        currentCommand = dbCommandParser.cleanseCommand(currentCommand);
+
+        if (dbCommandParser.isNestedScript(currentCommand)) {
+          // if this is a nested sql script then flatten it
+          String currScript = dbCommandParser.getScriptName(currentCommand);
+          sb.append(buildCommand(dbCommandParser, scriptDir, currScript));
+        } else {
+          // Now we have a complete statement, process it
+          // write the line to buffer
+          sb.append(currentCommand);
+          sb.append(System.getProperty("line.separator"));
+        }
+      }
+      currentCommand = null;
+    }
+    bfReader.close();
+    return sb.toString();
+  }
+
+  // run beeline on the given sentry store scrip, flatten the nested scripts into single file
+  private void runBeeLine(String scriptDir, String scriptFile) throws IOException {
+    NestedScriptParser dbCommandParser =
+        SentrySchemaHelper.getDbCommandParser(dbType);
+    dbCommandParser.setDbOpts(getDbOpts());
+    // expand the nested script
+    String sqlCommands = buildCommand(dbCommandParser, scriptDir, scriptFile);
+    File tmpFile = File.createTempFile("schematool", ".sql");
+    tmpFile.deleteOnExit();
+
+    // write out the buffer into a file. Add beeline commands for autocommit and close
+    try (FileWriter fstream = new FileWriter(tmpFile.getPath());
+      BufferedWriter out = new BufferedWriter(fstream)) {
+
+      out.write("!set Silent " + verbose + System.getProperty("line.separator"));
+      out.write("!autocommit on" + System.getProperty("line.separator"));
+      out.write("!set Isolation TRANSACTION_READ_COMMITTED"
+          + System.getProperty("line.separator"));
+      out.write("!set AllowMultiLineCommand false"
+          + System.getProperty("line.separator"));
+      out.write(sqlCommands);
+      out.write("!closeall" + System.getProperty("line.separator"));
+      out.close();
+    }
+    runBeeLine(tmpFile.getPath());
+  }
+
+  // Generate the beeline args per hive conf and execute the given script
+  public void runBeeLine(String sqlScriptFile) throws IOException {
+    List<String> argList = new ArrayList<String>();
+    argList.add("-u");
+    argList.add(connectionURL);
+    argList.add("-d");
+    argList
+        .add(driver);
+    argList.add("-n");
+    argList.add(userName);
+    argList.add("-p");
+    argList.add(passWord);
+    argList.add("-f");
+    argList.add(sqlScriptFile);
+
+    BeeLine beeLine = new BeeLine();
+    if (!verbose) {
+      beeLine.setOutputStream(new PrintStream(new NullOutputStream()));
+      // beeLine.getOpts().setSilent(true);
+    }
+    // beeLine.getOpts().setAllowMultiLineCommand(false);
+    // beeLine.getOpts().setIsolation("TRANSACTION_READ_COMMITTED");
+    int status = beeLine.begin(argList.toArray(new String[0]), null);
+    if (status != 0) {
+      throw new IOException("Schema script failed, errorcode " + status);
+    }
+  }
+
+  private String getValidConfVar(String confVar) throws IOException {
+    String confVarKey = confVar;
+    String confVarValue = sentryConf.get(confVarKey);
+    if (confVarValue == null || confVarValue.isEmpty()) {
+      throw new IOException("Empty " + confVar);
+    }
+    return confVarValue;
+  }
+
+  // Create the required command line options
+  @SuppressWarnings("static-access")
+  private static void initOptions(Options cmdLineOptions) {
+    Option help = new Option("help", "print this message");
+    Option upgradeOpt = new Option("upgradeSchema", "Schema upgrade");
+    Option upgradeFromOpt = OptionBuilder.withArgName("upgradeFrom").hasArg().
+                withDescription("Schema upgrade from a version").
+                create("upgradeSchemaFrom");
+    Option initOpt = new Option("initSchema", "Schema initialization");
+    Option initToOpt = OptionBuilder.withArgName("initTo").hasArg().
+                withDescription("Schema initialization to a version").
+                create("initSchemaTo");
+    Option infoOpt = new Option("info", "Show config and schema details");
+
+    OptionGroup optGroup = new OptionGroup();
+    optGroup.addOption(upgradeOpt).addOption(initOpt).
+                addOption(help).addOption(upgradeFromOpt).
+                addOption(initToOpt).addOption(infoOpt);
+    optGroup.setRequired(true);
+
+    Option userNameOpt = OptionBuilder.withArgName("user")
+                .hasArg()
+                .withDescription("Override config file user name")
+                .create("userName");
+    Option passwdOpt = OptionBuilder.withArgName("password")
+                .hasArg()
+                 .withDescription("Override config file password")
+                 .create("passWord");
+    Option dbTypeOpt = OptionBuilder.withArgName("databaseType")
+                .hasArg().withDescription("Metastore database type [" +
+                SentrySchemaHelper.DB_DERBY + "," +
+                SentrySchemaHelper.DB_MYSQL + "," +
+                SentrySchemaHelper.DB_ORACLE + "," +
+                SentrySchemaHelper.DB_POSTGRACE + "," +
+                SentrySchemaHelper.DB_DB2 + "]")
+                .create("dbType");
+    Option dbOpts = OptionBuilder.withArgName("databaseOpts")
+                .hasArgs().withDescription("Backend DB specific options")
+                .create("dbOpts");
+
+    Option dryRunOpt = new Option("dryRun", "list SQL scripts (no execute)");
+    Option verboseOpt = new Option("verbose", "only print SQL statements");
+
+    Option configOpt = OptionBuilder.withArgName("confName").hasArgs()
+        .withDescription("Sentry Service configuration file").isRequired(true)
+        .create(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
+
+    cmdLineOptions.addOption(help);
+    cmdLineOptions.addOption(dryRunOpt);
+    cmdLineOptions.addOption(userNameOpt);
+    cmdLineOptions.addOption(passwdOpt);
+    cmdLineOptions.addOption(dbTypeOpt);
+    cmdLineOptions.addOption(verboseOpt);
+    cmdLineOptions.addOption(dbOpts);
+    cmdLineOptions.addOption(configOpt);
+    cmdLineOptions.addOptionGroup(optGroup);
+  }
+
+  public static class CommandImpl implements Command {
+    @Override
+    public void run(String[] args) throws Exception {
+      CommandLineParser parser = new GnuParser();
+      CommandLine line = null;
+      String dbType = null;
+      String schemaVer = null;
+      Options cmdLineOptions = new Options();
+      String configFileName = null;
+
+      // Argument handling
+      initOptions(cmdLineOptions);
+      try {
+        line = parser.parse(cmdLineOptions, args);
+      } catch (ParseException e) {
+        System.err.println("SentrySchemaTool:Parsing failed.  Reason: "
+            + e.getLocalizedMessage());
+        printAndExit(cmdLineOptions);
+      }
+
+      if (line.hasOption("help")) {
+        HelpFormatter formatter = new HelpFormatter();
+        formatter.printHelp("schemaTool", cmdLineOptions);
+        return;
+      }
+
+      if (line.hasOption("dbType")) {
+        dbType = line.getOptionValue("dbType");
+        if (!dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)
+            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_MYSQL)
+            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_POSTGRACE)
+            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_ORACLE)
+            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DB2)) {
+          System.err.println("Unsupported dbType " + dbType);
+          printAndExit(cmdLineOptions);
+        }
+      } else {
+        System.err.println("no dbType supplied");
+        printAndExit(cmdLineOptions);
+      }
+      if (line.hasOption(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG)) {
+        configFileName = line
+            .getOptionValue(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
+      } else {
+        System.err.println("no config file specified");
+        printAndExit(cmdLineOptions);
+      }
+      try {
+        SentrySchemaTool schemaTool = new SentrySchemaTool(
+            SentryService.loadConfig(configFileName), dbType);
+
+        if (line.hasOption("userName")) {
+          schemaTool.setUserName(line.getOptionValue("userName"));
+        }
+        if (line.hasOption("passWord")) {
+          schemaTool.setPassWord(line.getOptionValue("passWord"));
+        }
+        if (line.hasOption("dryRun")) {
+          schemaTool.setDryRun(true);
+        }
+        if (line.hasOption("verbose")) {
+          schemaTool.setVerbose(true);
+        }
+        if (line.hasOption("dbOpts")) {
+          schemaTool.setDbOpts(line.getOptionValue("dbOpts"));
+        }
+
+        if (line.hasOption("info")) {
+          schemaTool.showInfo();
+        } else if (line.hasOption("upgradeSchema")) {
+          schemaTool.doUpgrade();
+        } else if (line.hasOption("upgradeSchemaFrom")) {
+          schemaVer = line.getOptionValue("upgradeSchemaFrom");
+          schemaTool.doUpgrade(schemaVer);
+        } else if (line.hasOption("initSchema")) {
+          schemaTool.doInit();
+        } else if (line.hasOption("initSchemaTo")) {
+          schemaVer = line.getOptionValue("initSchemaTo");
+          schemaTool.doInit(schemaVer);
+        } else {
+          System.err.println("no valid option supplied");
+          printAndExit(cmdLineOptions);
+        }
+      } catch (SentryUserException e) {
+        System.err.println(e);
+        if (line.hasOption("verbose")) {
+          e.printStackTrace();
+        }
+        System.err.println("*** Sentry schemaTool failed ***");
+        System.exit(1);
+      } catch (MalformedURLException e) {
+        System.err.println(e);
+        if (line.hasOption("verbose")) {
+          e.printStackTrace();
+        }
+        System.err.println("*** Sentry schemaTool failed ***");
+        System.exit(1);
+      }
+      System.out.println("Sentry schemaTool completed");
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellCommon.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellCommon.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellCommon.java
new file mode 100644
index 0000000..94800a4
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellCommon.java
@@ -0,0 +1,284 @@
+/**
+ * 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.sentry.cli.tools;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.Parser;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * SentryShellCommon provides the function for parsing the argument.
+ * For hive model and generic model, child class should be implemented as a sentry admin tool.
+ */
+abstract public class SentryShellCommon {
+
+  public enum TYPE { kafka, hive, solr, sqoop };
+
+  public static final String OPTION_DESC_HELP = "Shell usage";
+  public static final String OPTION_DESC_CONF = "sentry-site file path";
+  public static final String OPTION_DESC_ROLE_NAME = "Role name";
+  public static final String OPTION_DESC_GROUP_NAME = "Group name";
+  public static final String OPTION_DESC_PRIVILEGE = "Privilege string";
+  public final static String OPTION_DESC_SERVICE = "Name of the service being managed";
+  public static final String PREFIX_MESSAGE_MISSING_OPTION = "Missing required option: ";
+
+  public static final String GROUP_SPLIT_CHAR = ",";
+
+  protected String roleName;
+  protected String serviceName;
+  protected String groupName;
+  protected String privilegeStr;
+  protected String confPath;
+  // flag for the command
+  protected boolean isCreateRole;
+  protected boolean isDropRole;
+  protected boolean isAddRoleGroup;
+  protected boolean isDeleteRoleGroup;
+  protected boolean isGrantPrivilegeRole;
+  protected boolean isRevokePrivilegeRole;
+  protected boolean isListRole;
+  protected boolean isListPrivilege;
+  protected boolean isListGroup;
+  protected boolean isPrintHelp;
+  // flag for the parameter check
+  protected boolean roleNameRequired;
+  protected boolean groupNameRequired;
+  protected boolean privilegeStrRequired;
+  protected TYPE type;
+
+  /**
+   * parse arguments
+   *
+   * <pre>
+   *   -conf,--sentry_conf             <filepath>                 sentry config file path
+   *   -cr,--create_role            -r <rolename>                 create role
+   *   -dr,--drop_role              -r <rolename>                 drop role
+   *   -arg,--add_role_group        -r <rolename>  -g <groupname> add role to group
+   *   -drg,--delete_role_group     -r <rolename>  -g <groupname> delete role from group
+   *   -gpr,--grant_privilege_role  -r <rolename>  -p <privilege> grant privilege to role
+   *   -rpr,--revoke_privilege_role -r <rolename>  -p <privilege> revoke privilege from role
+   *   -lr,--list_role              -g <groupname>                list roles for group
+   *   -lp,--list_privilege         -r <rolename>                 list privilege for role
+   *   -lg,--list_group                                           list all groups associated with all roles
+   *   -t,--type                    <typename>                    the shell for hive model or generic model
+   * </pre>
+   *
+   * @param args
+   */
+  protected boolean parseArgs(String[] args) {
+    Options simpleShellOptions = new Options();
+
+    setupOptions(simpleShellOptions);
+
+
+
+    // help option
+    Option helpOpt = new Option("h", "help", false, OPTION_DESC_HELP);
+    helpOpt.setRequired(false);
+    simpleShellOptions.addOption(helpOpt);
+
+    // this Options is parsed first for help option
+    Options helpOptions = new Options();
+    helpOptions.addOption(helpOpt);
+
+    try {
+      Parser parser = new GnuParser();
+
+      // parse help option first
+      CommandLine cmd = parser.parse(helpOptions, args, true);
+      for (Option opt : cmd.getOptions()) {
+        if (opt.getOpt().equals("h")) {
+          // get the help option, print the usage and exit
+          usage(simpleShellOptions);
+          return false;
+        }
+      }
+
+      // without help option
+      cmd = parser.parse(simpleShellOptions, args);
+
+      parseOptions(cmd);
+    } catch (ParseException pe) {
+      System.out.println(pe.getMessage());
+      usage(simpleShellOptions);
+      return false;
+    }
+    return true;
+  }
+
+  protected void setupOptions(Options simpleShellOptions) {
+    OptionGroup simpleShellOptGroup = getMainOptions();
+    simpleShellOptions.addOptionGroup(simpleShellOptGroup);
+
+    Option sOpt = new Option("s", "service", true, OPTION_DESC_SERVICE);
+    sOpt.setRequired(false);
+    simpleShellOptions.addOption(sOpt);
+
+    // optional args
+    Option pOpt = new Option("p", "privilege", true, OPTION_DESC_PRIVILEGE);
+    pOpt.setRequired(false);
+    simpleShellOptions.addOption(pOpt);
+
+    Option gOpt = new Option("g", "groupname", true, OPTION_DESC_GROUP_NAME);
+    gOpt.setRequired(false);
+    simpleShellOptions.addOption(gOpt);
+
+    Option rOpt = new Option("r", "rolename", true, OPTION_DESC_ROLE_NAME);
+    rOpt.setRequired(false);
+    simpleShellOptions.addOption(rOpt);
+
+    // this argument should also be parsed in the bin/sentryShell
+    Option tOpt = new Option("t", "type", true, "[hive|solr|sqoop|.....]");
+    tOpt.setRequired(false);
+    simpleShellOptions.addOption(tOpt);
+
+    // file path of sentry-site
+    Option sentrySitePathOpt = new Option("conf", "sentry_conf", true, OPTION_DESC_CONF);
+    sentrySitePathOpt.setRequired(true);
+    simpleShellOptions.addOption(sentrySitePathOpt);
+  }
+
+  protected OptionGroup getMainOptions() {
+    OptionGroup simpleShellOptGroup = new OptionGroup();
+    Option crOpt = new Option("cr", "create_role", false, "Create role");
+    crOpt.setRequired(false);
+
+    Option drOpt = new Option("dr", "drop_role", false, "Drop role");
+    drOpt.setRequired(false);
+
+    Option argOpt = new Option("arg", "add_role_group", false, "Add role to group");
+    argOpt.setRequired(false);
+
+    Option drgOpt = new Option("drg", "delete_role_group", false, "Delete role from group");
+    drgOpt.setRequired(false);
+
+    Option gprOpt = new Option("gpr", "grant_privilege_role", false, "Grant privilege to role");
+    gprOpt.setRequired(false);
+
+    Option rprOpt = new Option("rpr", "revoke_privilege_role", false, "Revoke privilege from role");
+    rprOpt.setRequired(false);
+
+    Option lrOpt = new Option("lr", "list_role", false, "List role");
+    lrOpt.setRequired(false);
+
+    Option lpOpt = new Option("lp", "list_privilege", false, "List privilege");
+    lpOpt.setRequired(false);
+
+    Option lgOpt = new Option("lg", "list_group", false, "List groups");
+    lgOpt.setRequired(false);
+
+
+    // required args group
+    simpleShellOptGroup.addOption(crOpt);
+    simpleShellOptGroup.addOption(drOpt);
+    simpleShellOptGroup.addOption(argOpt);
+    simpleShellOptGroup.addOption(drgOpt);
+    simpleShellOptGroup.addOption(gprOpt);
+    simpleShellOptGroup.addOption(rprOpt);
+    simpleShellOptGroup.addOption(lrOpt);
+    simpleShellOptGroup.addOption(lpOpt);
+    simpleShellOptGroup.addOption(lgOpt);
+    simpleShellOptGroup.setRequired(true);
+    return simpleShellOptGroup;
+  }
+
+  protected void parseOptions(CommandLine cmd) throws ParseException {
+    for (Option opt : cmd.getOptions()) {
+      if (opt.getOpt().equals("p")) {
+        privilegeStr = opt.getValue();
+      } else if (opt.getOpt().equals("g")) {
+        groupName = opt.getValue();
+      } else if (opt.getOpt().equals("r")) {
+        roleName = opt.getValue();
+      } else if (opt.getOpt().equals("s")) {
+        serviceName = opt.getValue();
+      } else if (opt.getOpt().equals("cr")) {
+        isCreateRole = true;
+        roleNameRequired = true;
+      } else if (opt.getOpt().equals("dr")) {
+        isDropRole = true;
+        roleNameRequired = true;
+      } else if (opt.getOpt().equals("arg")) {
+        isAddRoleGroup = true;
+        roleNameRequired = true;
+        groupNameRequired = true;
+      } else if (opt.getOpt().equals("drg")) {
+        isDeleteRoleGroup = true;
+        roleNameRequired = true;
+        groupNameRequired = true;
+      } else if (opt.getOpt().equals("gpr")) {
+        isGrantPrivilegeRole = true;
+        roleNameRequired = true;
+        privilegeStrRequired = true;
+      } else if (opt.getOpt().equals("rpr")) {
+        isRevokePrivilegeRole = true;
+        roleNameRequired = true;
+        privilegeStrRequired = true;
+      } else if (opt.getOpt().equals("lr")) {
+        isListRole = true;
+      } else if (opt.getOpt().equals("lp")) {
+        isListPrivilege = true;
+        roleNameRequired = true;
+      } else if (opt.getOpt().equals("lg")) {
+        isListGroup = true;
+      } else if (opt.getOpt().equals("conf")) {
+        confPath = opt.getValue();
+      } else if (opt.getOpt().equals("t")) {
+        type = TYPE.valueOf(opt.getValue());
+      }
+    }
+    checkRequiredParameter(roleNameRequired, roleName, OPTION_DESC_ROLE_NAME);
+    checkRequiredParameter(groupNameRequired, groupName, OPTION_DESC_GROUP_NAME);
+    checkRequiredParameter(privilegeStrRequired, privilegeStr, OPTION_DESC_PRIVILEGE);
+  }
+
+  protected void checkRequiredParameter(boolean isRequired, String paramValue, String paramName) throws ParseException {
+    if (isRequired && StringUtils.isEmpty(paramValue)) {
+      throw new ParseException(PREFIX_MESSAGE_MISSING_OPTION + paramName);
+    }
+  }
+
+  // print usage
+  private void usage(Options sentryOptions) {
+    HelpFormatter formatter = new HelpFormatter();
+    formatter.printHelp("sentryShell", sentryOptions);
+  }
+
+  // hive model and generic model should implement this method
+  public abstract void run() throws Exception;
+
+  @VisibleForTesting
+  public boolean executeShell(String[] args) throws Exception {
+    boolean result = true;
+    if (parseArgs(args)) {
+      run();
+    } else {
+      result = false;
+    }
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellGeneric.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellGeneric.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellGeneric.java
new file mode 100644
index 0000000..6d25617
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellGeneric.java
@@ -0,0 +1,157 @@
+/**
+ * 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.sentry.cli.tools;
+
+import com.google.common.collect.Sets;
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.provider.common.AuthorizationComponent;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
+import org.apache.sentry.cli.tools.command.GenericShellCommand;
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * SentryShellGeneric is an admin tool, and responsible for the management of repository.
+ * The following commands are supported:
+ * create role, drop role, add group to role, grant privilege to role,
+ * revoke privilege from role, list roles, list privilege for role.
+ */
+public class SentryShellGeneric extends SentryShellCommon {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellGeneric.class);
+  private static final String KAFKA_SERVICE_NAME = "sentry.service.client.kafka.service.name";
+  private static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
+  private static final String SQOOP_SERVICE_NAME = "sentry.service.client.sqoop.service.name";
+
+  @Override
+  public void run() throws Exception {
+    String component = getComponent();
+    Configuration conf = getSentryConf();
+
+    String service = getService(conf);
+    try (SentryGenericServiceClient client =
+                SentryGenericServiceClientFactory.create(conf)) {
+      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+      String requestorName = ugi.getShortUserName();
+      TSentryPrivilegeConverter converter = getPrivilegeConverter(component, service);
+      ShellCommand command = new GenericShellCommand(client, component, service, converter);
+
+      // check the requestor name
+      if (StringUtils.isEmpty(requestorName)) {
+        // The exception message will be recorded in log file.
+        throw new Exception("The requestor name is empty.");
+      }
+
+      if (isCreateRole) {
+        command.createRole(requestorName, roleName);
+      } else if (isDropRole) {
+        command.dropRole(requestorName, roleName);
+      } else if (isAddRoleGroup) {
+        Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
+        command.grantRoleToGroups(requestorName, roleName, groups);
+      } else if (isDeleteRoleGroup) {
+        Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
+        command.revokeRoleFromGroups(requestorName, roleName, groups);
+      } else if (isGrantPrivilegeRole) {
+        command.grantPrivilegeToRole(requestorName, roleName, privilegeStr);
+      } else if (isRevokePrivilegeRole) {
+        command.revokePrivilegeFromRole(requestorName, roleName, privilegeStr);
+      } else if (isListRole) {
+        List<String> roles = command.listRoles(requestorName, groupName);
+        for (String role : roles) {
+          System.out.println(role);
+        }
+      } else if (isListPrivilege) {
+        List<String> privileges = command.listPrivileges(requestorName, roleName);
+        for (String privilege : privileges) {
+          System.out.println(privilege);
+        }
+      } else if (isListGroup) {
+        List<String> groups = command.listGroupRoles(requestorName);
+        for (String group : groups) {
+          System.out.println(group);
+        }
+      }
+    }
+  }
+
+  protected GenericPrivilegeConverter getPrivilegeConverter(String component, String service) {
+    return new GenericPrivilegeConverter(component, service);
+  }
+
+  protected String getComponent() throws Exception {
+    if (type == TYPE.kafka) {
+      return AuthorizationComponent.KAFKA;
+    } else if (type == TYPE.solr) {
+      return "SOLR";
+    } else if (type == TYPE.sqoop) {
+      return AuthorizationComponent.SQOOP;
+    }
+
+    throw new Exception("Invalid type specified for SentryShellGeneric: " + type);
+  }
+
+  protected String getService(Configuration conf) throws Exception {
+    if (type == TYPE.kafka) {
+      return conf.get(KAFKA_SERVICE_NAME, AuthorizationComponent.KAFKA);
+    } else if (type == TYPE.solr) {
+      return conf.get(SOLR_SERVICE_NAME, "service1");
+    } else if (type == TYPE.sqoop) {
+      return conf.get(SQOOP_SERVICE_NAME, "sqoopServer1");
+    }
+
+    throw new Exception("Invalid type specified for SentryShellGeneric: " + type);
+  }
+
+  private Configuration getSentryConf() {
+    Configuration conf = new Configuration();
+    conf.addResource(new Path(confPath), true);
+    return conf;
+  }
+
+  public static void main(String[] args) throws Exception {
+    SentryShellGeneric sentryShell = new SentryShellGeneric();
+    try {
+      sentryShell.executeShell(args);
+    } catch (Exception e) {
+      LOGGER.error(e.getMessage(), e);
+      Throwable current = e;
+      // find the first printable message;
+      while (current != null && current.getMessage() == null) {
+        current = current.getCause();
+      }
+      String error = "";
+      if (current != null && current.getMessage() != null) {
+        error = "Message: " + current.getMessage();
+      }
+      System.out.println("The operation failed. " + error);
+      System.exit(1);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellHive.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellHive.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellHive.java
new file mode 100644
index 0000000..884ed91
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellHive.java
@@ -0,0 +1,118 @@
+/**
+ * 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.sentry.cli.tools;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.cli.tools.command.hive.*;
+import org.apache.sentry.service.thrift.SentryServiceClientFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+
+/**
+ * SentryShellHive is an admin tool, and responsible for the management of repository.
+ * The following function are supported:
+ * create role, drop role, add group to role, delete group from role, grant privilege to role,
+ * revoke privilege from role, list roles for group, list privilege for role.
+ */
+public class SentryShellHive extends SentryShellCommon {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellHive.class);
+
+  public void run() throws Exception {
+
+    try(SentryPolicyServiceClient client =
+                SentryServiceClientFactory.create(getSentryConf())) {
+      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+      String requestorName = ugi.getShortUserName();
+      ShellCommand command = new HiveShellCommand(client);
+
+      // check the requestor name
+      if (StringUtils.isEmpty(requestorName)) {
+        // The exception message will be recorded in the log file.
+        throw new Exception("The requestor name is empty.");
+      }
+
+      if (isCreateRole) {
+        command.createRole(requestorName, roleName);
+      } else if (isDropRole) {
+        command.dropRole(requestorName, roleName);
+      } else if (isAddRoleGroup) {
+        Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
+        command.grantRoleToGroups(requestorName, roleName, groups);
+      } else if (isDeleteRoleGroup) {
+        Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
+        command.revokeRoleFromGroups(requestorName, roleName, groups);
+      } else if (isGrantPrivilegeRole) {
+        command.grantPrivilegeToRole(requestorName, roleName, privilegeStr);
+      } else if (isRevokePrivilegeRole) {
+        command.revokePrivilegeFromRole(requestorName, roleName, privilegeStr);
+      } else if (isListRole) {
+        List<String> roles = command.listRoles(requestorName, groupName);
+        for (String role : roles) {
+          System.out.println(role);
+        }
+      } else if (isListPrivilege) {
+        List<String> privileges = command.listPrivileges(requestorName, roleName);
+        for (String privilege : privileges) {
+          System.out.println(privilege);
+        }
+      } else if (isListGroup) {
+        List<String> groups = command.listGroupRoles(requestorName);
+        for (String group : groups) {
+          System.out.println(group);
+        }
+      }
+    }
+  }
+
+  private Configuration getSentryConf() {
+    Configuration conf = new Configuration();
+    conf.addResource(new Path(confPath), true);
+    return conf;
+  }
+
+  public static void main(String[] args) throws Exception {
+    SentryShellHive sentryShell = new SentryShellHive();
+    try {
+      sentryShell.executeShell(args);
+    } catch (Exception e) {
+      LOGGER.error(e.getMessage(), e);
+      Throwable current =  e;
+      // find the first printable message;
+      while (current != null && current.getMessage() == null) {
+        current = current.getCause();
+      }
+
+      if (current != null) {
+        System.out.println("The operation failed." +
+           (current.getMessage() == null ? "" : "  Message: " + current.getMessage()));
+      }
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellIndexer.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellIndexer.java
new file mode 100644
index 0000000..c7f854f
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryShellIndexer.java
@@ -0,0 +1,124 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.sentry.cli.tools;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionGroup;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.hadoop.conf.Configuration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
+import static org.apache.sentry.service.thrift.ServiceConstants.ClientConfig.SERVICE_NAME;
+
+/**
+ * SentryShellIndexer is an admin tool, and responsible for the management of repository.
+ * The following commands are supported:
+ * create role, drop role, add group to role, grant privilege to role,
+ * revoke privilege from role, list roles, list privilege for role.
+ */
+public class SentryShellIndexer extends SentryShellGeneric {
+
+  protected boolean isMigration = false;
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellIndexer.class);
+
+  private final SentryConfigToolIndexer configTool = new SentryConfigToolIndexer();
+
+  @Override
+  protected void setupOptions(Options simpleShellOptions) {
+    super.setupOptions(simpleShellOptions);
+    configTool.setupOptions(simpleShellOptions);
+  }
+
+  @Override
+  protected void parseOptions(CommandLine cmd) throws ParseException {
+    super.parseOptions(cmd);
+    configTool.parseOptions(cmd);
+    for (Option opt : cmd.getOptions()) {
+      if (opt.getOpt().equals("mgr")) {
+        isMigration = true;
+      }
+    }
+  }
+
+  @Override
+  protected OptionGroup getMainOptions() {
+    OptionGroup mainOptions = super.getMainOptions();
+    Option mgrOpt = new Option("mgr", "migrate", false, "Migrate ini file to Sentry service");
+    mgrOpt.setRequired(false);
+    mainOptions.addOption(mgrOpt);
+    return mainOptions;
+  }
+
+  /**
+   * Processes the necessary command based on the arguments parsed earlier.
+   * @throws Exception
+   */
+  @Override
+  public void run() throws Exception {
+
+    if (isMigration) {
+      configTool.run();
+      return;
+    }
+
+    super.run();
+  }
+
+  @Override
+  protected String getComponent() throws Exception {
+    return HBASE_INDEXER;
+  }
+
+  @Override
+  protected String getService(Configuration conf) throws Exception {
+    String service = conf.get(SERVICE_NAME, serviceName);
+    if (service == null) {
+      throw new IllegalArgumentException("Service was not defined. Please, use -s command option, or sentry.provider.backend.generic.service-name configuration entry.");
+    }
+    return service;
+  }
+
+  /**
+   * Entry-point for Hbase indexer cli tool.
+   * @param args
+   * @throws Exception
+   */
+  public static void main(String[] args) throws Exception {
+    SentryShellIndexer sentryShell = new SentryShellIndexer();
+    try {
+      sentryShell.executeShell(args);
+    } catch (Exception e) {
+      LOGGER.error(e.getMessage(), e);
+      Throwable current = e;
+      // find the first printable message;
+      while (current != null && current.getMessage() == null) {
+        current = current.getCause();
+      }
+      System.out.println("The operation failed." +
+              (current.getMessage() == null ? "" : "  Message: " + current.getMessage()));
+      System.exit(1);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/ShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/ShellCommand.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/ShellCommand.java
new file mode 100644
index 0000000..9a141c3
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/ShellCommand.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.sentry.cli.tools;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.sentry.core.common.exception.SentryUserException;
+
+/**
+ * The interface for all admin commands, eg, CreateRoleCmd. It is independent of the underlying mechanism (i.e. Generic or Hive)
+ */
+public interface ShellCommand {
+
+  void createRole(String requestorName, String roleName) throws SentryUserException;
+
+  void dropRole(String requestorName, String roleName) throws SentryUserException;
+
+  void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException;
+
+  void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException;
+
+  void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException;
+
+  void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException;
+
+  List<String> listRoles(String requestorName, String group) throws SentryUserException;
+
+  List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException;
+
+  List<String> listGroupRoles(String requestorName) throws SentryUserException;
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/GenericShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/GenericShellCommand.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/GenericShellCommand.java
new file mode 100644
index 0000000..3e0da50
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/GenericShellCommand.java
@@ -0,0 +1,156 @@
+/**
+ * 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.sentry.cli.tools.command;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.apache.sentry.cli.tools.ShellCommand;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
+
+/**
+ * The ShellCommand implementation for the Generic clients
+ */
+public class GenericShellCommand implements ShellCommand {
+
+  private final SentryGenericServiceClient client;
+  private final String component;
+  private final TSentryPrivilegeConverter converter;
+  private final String serviceName;
+
+  public GenericShellCommand(SentryGenericServiceClient client, String component, String serviceName,
+                             TSentryPrivilegeConverter converter) {
+    this.client = client;
+    this.component = component;
+    this.serviceName = serviceName;
+    this.converter = converter;
+  }
+
+  public void createRole(String requestorName, String roleName) throws SentryUserException {
+    client.createRole(requestorName, roleName, component);
+  }
+
+  public void dropRole(String requestorName, String roleName) throws SentryUserException {
+    client.dropRole(requestorName, roleName, component);
+  }
+
+  public void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException {
+    TSentryPrivilege sentryPrivilege = converter.fromString(privilege);
+    client.grantPrivilege(requestorName, roleName, component, sentryPrivilege);
+  }
+
+  public void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
+    client.grantRoleToGroups(requestorName, roleName, component, groups);
+  }
+
+  public void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException {
+    TSentryPrivilege sentryPrivilege = converter.fromString(privilege);
+    client.revokePrivilege(requestorName, roleName, component, sentryPrivilege);
+  }
+
+  public void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
+    client.revokeRoleFromGroups(requestorName, roleName, component, groups);
+  }
+
+  public List<String> listRoles(String requestorName, String group) throws SentryUserException {
+    Set<TSentryRole> roles;
+    if (StringUtils.isEmpty(group)) {
+      roles = client.listAllRoles(requestorName, component);
+    } else {
+      roles = client.listRolesByGroupName(requestorName, group, component);
+    }
+
+    List<String> result = new ArrayList<>();
+    if (roles != null) {
+      for (TSentryRole role : roles) {
+        result.add(role.getRoleName());
+      }
+    }
+
+    return result;
+  }
+
+  public List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException {
+    Set<TSentryPrivilege> privileges = client
+        .listAllPrivilegesByRoleName(requestorName, roleName, component, serviceName);
+
+    List<String> result = new ArrayList<>();
+    if (privileges != null) {
+      for (TSentryPrivilege privilege : privileges) {
+        String privilegeStr = converter.toString(privilege);
+        result.add(privilegeStr);
+      }
+    }
+
+    return result;
+  }
+
+  public List<String> listGroupRoles(String requestorName) throws SentryUserException {
+    Set<TSentryRole> roles = client.listAllRoles(requestorName, component);
+    if (roles == null || roles.isEmpty()) {
+      return Collections.emptyList();
+    }
+
+    // Set of all group names
+    Set<String> groupNames = new HashSet<>();
+
+    // Map group to set of roles
+    Map<String, Set<String>> groupInfo = new HashMap<>();
+
+    // Get all group names
+    for (TSentryRole role: roles) {
+      for (String group : role.getGroups()) {
+        groupNames.add(group);
+        Set<String> groupRoles = groupInfo.get(group);
+        if (groupRoles != null) {
+          // Add a new or existing role
+          groupRoles.add(role.getRoleName());
+          continue;
+        }
+        // Never seen this group before
+        groupRoles = new HashSet<>();
+        groupRoles.add(role.getRoleName());
+        groupInfo.put(group, groupRoles);
+      }
+    }
+
+    List<String> groups = new ArrayList<>(groupNames);
+
+    // Produce printable result as
+    // group1 = role1, role2, ...
+    // group2 = ...
+    List<String> result = new LinkedList<>();
+    for (String groupName: groups) {
+      result.add(groupName + " = " + StringUtils.join(groupInfo.get(groupName), ", "));
+    }
+
+    return result;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/CommandUtil.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/CommandUtil.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/CommandUtil.java
new file mode 100644
index 0000000..b06732e
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/CommandUtil.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.sentry.cli.tools.command.hive;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
+import org.apache.sentry.service.thrift.ServiceConstants;
+
+public final class CommandUtil {
+
+  public static final String SPLIT_CHAR = ",";
+
+  private CommandUtil() {
+    // Make constructor private to avoid instantiation
+  }
+
+  // check the privilege value for the specific privilege scope
+  // eg, for the table scope, server and database can't be empty
+  public static void validatePrivilegeHierarchy(TSentryPrivilege tSentryPrivilege) throws IllegalArgumentException {
+    String serverName = tSentryPrivilege.getServerName();
+    String dbName = tSentryPrivilege.getDbName();
+    String tableName = tSentryPrivilege.getTableName();
+    String columnName = tSentryPrivilege.getColumnName();
+    String uri = tSentryPrivilege.getURI();
+    if (ServiceConstants.PrivilegeScope.SERVER.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+      if (StringUtils.isEmpty(serverName)) {
+        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+      }
+    } else if (ServiceConstants.PrivilegeScope.URI.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+      if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(uri)) {
+        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+      }
+    } else if (ServiceConstants.PrivilegeScope.DATABASE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+      if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)) {
+        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+      }
+    } else if (ServiceConstants.PrivilegeScope.TABLE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
+      if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)
+              || StringUtils.isEmpty(tableName)) {
+        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+      }
+    } else if (ServiceConstants.PrivilegeScope.COLUMN.toString().equals(tSentryPrivilege.getPrivilegeScope())
+      && (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)
+              || StringUtils.isEmpty(tableName) || StringUtils.isEmpty(columnName))) {
+        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/HiveShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/HiveShellCommand.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/HiveShellCommand.java
new file mode 100644
index 0000000..1d11c3b
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/command/hive/HiveShellCommand.java
@@ -0,0 +1,152 @@
+/**
+ * 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.sentry.cli.tools.command.hive;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
+import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
+import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+import org.apache.sentry.cli.tools.ShellCommand;
+import org.apache.sentry.service.thrift.SentryServiceUtil;
+
+/**
+ * The ShellCommand implementation for Hive.
+ */
+public class HiveShellCommand implements ShellCommand {
+
+  private final SentryPolicyServiceClient client;
+
+  public HiveShellCommand(SentryPolicyServiceClient client) {
+    this.client = client;
+  }
+
+  public void createRole(String requestorName, String roleName) throws SentryUserException {
+    client.createRole(requestorName, roleName);
+  }
+
+  public void dropRole(String requestorName, String roleName) throws SentryUserException {
+    client.dropRole(requestorName, roleName);
+  }
+
+  public void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException {
+    TSentryPrivilege tSentryPrivilege = SentryServiceUtil.convertToTSentryPrivilege(privilege);
+    CommandUtil.validatePrivilegeHierarchy(tSentryPrivilege);
+    client.grantPrivilege(requestorName, roleName, tSentryPrivilege);
+  }
+
+  public void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
+    client.grantRoleToGroups(requestorName, roleName, groups);
+  }
+
+  public void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException {
+    TSentryPrivilege tSentryPrivilege = SentryServiceUtil.convertToTSentryPrivilege(privilege);
+    CommandUtil.validatePrivilegeHierarchy(tSentryPrivilege);
+    client.revokePrivilege(requestorName, roleName, tSentryPrivilege);
+  }
+
+  public void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
+    client.revokeRoleFromGroups(requestorName, roleName, groups);
+  }
+
+  public List<String> listRoles(String requestorName, String group) throws SentryUserException {
+    Set<TSentryRole> roles;
+    if (StringUtils.isEmpty(group)) {
+      roles = client.listAllRoles(requestorName);
+    } else {
+      roles = client.listRolesByGroupName(requestorName, group);
+    }
+
+    List<String> result = new ArrayList<>();
+    if (roles != null) {
+      for (TSentryRole role : roles) {
+        result.add(role.getRoleName());
+      }
+    }
+
+    return result;
+  }
+
+  public List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException {
+    Set<TSentryPrivilege> privileges = client
+        .listAllPrivilegesByRoleName(requestorName, roleName);
+
+    List<String> result = new ArrayList<>();
+    if (privileges != null) {
+      for (TSentryPrivilege privilege : privileges) {
+        String privilegeStr = SentryServiceUtil.convertTSentryPrivilegeToStr(privilege);
+        result.add(privilegeStr);
+      }
+    }
+    return result;
+  }
+
+  public List<String> listGroupRoles(String requestorName) throws SentryUserException {
+    Set<TSentryRole> roles = client.listAllRoles(requestorName);
+    if (roles == null || roles.isEmpty()) {
+      return Collections.emptyList();
+    }
+
+    // Set of all group names
+    Set<String> groupNames = new HashSet<>();
+
+    // Map group to set of roles
+    Map<String, Set<String>> groupInfo = new HashMap<>();
+
+    // Get all group names
+    for (TSentryRole role: roles) {
+      for (TSentryGroup group : role.getGroups()) {
+        String groupName = group.getGroupName();
+        groupNames.add(groupName);
+        Set<String> groupRoles = groupInfo.get(groupName);
+        if (groupRoles != null) {
+          // Add a new or existing role
+          groupRoles.add(role.getRoleName());
+          continue;
+        }
+        // Never seen this group before
+        groupRoles = new HashSet<>();
+        groupRoles.add(role.getRoleName());
+        groupInfo.put(groupName, groupRoles);
+      }
+    }
+
+    List<String> groups = new ArrayList<>(groupNames);
+
+    // Produce printable result as
+    // group1 = role1, role2, ...
+    // group2 = ...
+    List<String> result = new LinkedList<>();
+    for (String groupName: groups) {
+      result.add(groupName + " = " + StringUtils.join(groupInfo.get(groupName), ", "));
+    }
+
+    return result;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
index b7652a5..863f992 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/GroupShell.java
@@ -23,7 +23,7 @@ import com.budhash.cliche.Shell;
 import com.budhash.cliche.ShellDependent;
 
 import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.tools.ShellCommand;
+import org.apache.sentry.cli.tools.ShellCommand;
 
 import java.util.Arrays;
 import java.util.Collections;

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
index 8b8898f..3ff6737 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/PrivsShell.java
@@ -24,7 +24,7 @@ import com.budhash.cliche.Shell;
 import com.budhash.cliche.ShellDependent;
 
 import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.tools.ShellCommand;
+import org.apache.sentry.cli.tools.ShellCommand;
 
 import java.util.Collections;
 import java.util.List;

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
index c014a30..42bce19 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/RolesShell.java
@@ -24,7 +24,7 @@ import com.budhash.cliche.Shell;
 import com.budhash.cliche.ShellDependent;
 
 import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.tools.ShellCommand;
+import org.apache.sentry.cli.tools.ShellCommand;
 
 import java.util.Collections;
 import java.util.List;

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
index d9952a9..04d65bd 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/shell/TopLevelShell.java
@@ -22,11 +22,11 @@ import org.apache.sentry.core.common.exception.SentryUserException;
 import org.apache.sentry.provider.common.AuthorizationComponent;
 import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
 import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
-import org.apache.sentry.provider.db.generic.tools.command.GenericShellCommand;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
+import org.apache.sentry.cli.tools.command.GenericShellCommand;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
 import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.provider.db.tools.ShellCommand;
-import org.apache.sentry.provider.db.tools.command.hive.HiveShellCommand;
+import org.apache.sentry.cli.tools.ShellCommand;
+import org.apache.sentry.cli.tools.command.hive.HiveShellCommand;
 
 import com.budhash.cliche.Command;
 import com.budhash.cliche.Param;


[3/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.

Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java
new file mode 100644
index 0000000..a275d18
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestPermissionsMigrationToolSolr.java
@@ -0,0 +1,362 @@
+ /**
+ * 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.sentry.cli.tools;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.common.ProviderBackendContext;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;import org.apache.sentry.provider.file.PolicyFile;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+import com.google.common.io.Files;
+
+public class TestPermissionsMigrationToolSolr extends SentryGenericServiceIntegrationBase {
+  private File confDir;
+  private File confPath;
+  private String requestorName = "";
+  private String service = "service1";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    setLocalGroupMapping("dev", Sets.newHashSet("dev_group"));
+    setLocalGroupMapping("user", Sets.newHashSet("user_group"));
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+
+    // clear roles and privileges
+    Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
+    for (TSentryRole tRole : tRoles) {
+      String role = tRole.getRoleName();
+      Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+          requestorName, role, SOLR, service);
+      for (TSentryPrivilege privilege : privileges) {
+        client.revokePrivilege(requestorName, role, SOLR, privilege);
+      }
+      client.dropRole(requestorName, role, SOLR);
+    }
+  }
+
+  @Test
+  public void testPermissionsMigrationFromSentrySvc_v1() throws Exception {
+    initializeSentryService();
+
+    String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath()};
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    sentryTool.executeConfigTool(args);
+
+    Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+    groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
+    groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
+    groupMapping.put("user_role", Sets.newHashSet("user_group"));
+
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryServiceState(groupMapping, privilegeMapping);
+  }
+
+  @Test
+  public void testPermissionsMigrationFromSentryPolicyFile_v1() throws Exception {
+    Path policyFilePath = initializeSentryPolicyFile();
+    Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini");
+
+    String[] args = { "-s", "1.8.0", "-p", policyFilePath.toFile().getAbsolutePath(),
+                      "-o", outputFilePath.toFile().getAbsolutePath() };
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    assertTrue(sentryTool.executeConfigTool(args));
+
+    Set<String> groups = new HashSet<>();
+    groups.add("admin_group");
+    groups.add("dev_group");
+    groups.add("user_group");
+
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryPolicyFile(groups, privilegeMapping, outputFilePath);
+  }
+
+  @Test
+  // For permissions created with Sentry 2.x, no migration necessary
+  public void testPermissionsMigrationFromSentrySvc_v2() throws Exception {
+    initializeSentryService();
+
+    String[] args = { "-s", "2.0.0", "-c", confPath.getAbsolutePath()};
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    sentryTool.executeConfigTool(args);
+
+    Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+    groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
+    groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
+    groupMapping.put("user_role", Sets.newHashSet("user_group"));
+
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("collection=admin->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryServiceState(groupMapping, privilegeMapping);
+  }
+
+  @Test
+  // For permissions created with Sentry 2.x, no migration necessary
+  public void testPermissionsMigrationFromSentryPolicyFile_v2() throws Exception {
+    Path policyFilePath = initializeSentryPolicyFile();
+    Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini");
+
+    String[] args = { "-s", "2.0.0", "-p", policyFilePath.toFile().getAbsolutePath(),
+                      "-o", outputFilePath.toFile().getAbsolutePath() };
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    assertTrue(sentryTool.executeConfigTool(args));
+
+    Set<String> groups = new HashSet<>();
+    groups.add("admin_group");
+    groups.add("dev_group");
+    groups.add("user_group");
+
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("collection=admin->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryPolicyFile(groups, privilegeMapping, outputFilePath);
+  }
+
+  @Test
+  public void testDryRunOption() throws Exception {
+    initializeSentryService();
+
+    String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath(), "--dry_run"};
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+    sentryTool.executeConfigTool(args);
+
+    Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+    groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
+    groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
+    groupMapping.put("user_role", Sets.newHashSet("user_group"));
+
+    // No change in the privileges
+    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+    privilegeMapping.put("admin_role",
+        Sets.newHashSet("collection=admin->action=*"));
+    privilegeMapping.put("dev_role",
+        Sets.newHashSet("collection=*->action=*"));
+    privilegeMapping.put("user_role",
+        Sets.newHashSet("collection=foo->action=*"));
+
+    verifySentryServiceState(groupMapping, privilegeMapping);
+  }
+
+  @Test
+  public void testInvalidToolArguments() throws Exception {
+    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
+
+    {
+      String[] args = { "-c", confPath.getAbsolutePath()};
+      assertFalse("The execution should have failed due to missing source version",
+          sentryTool.executeConfigTool(args));
+    }
+
+    {
+      String[] args = { "-s", "1.8.0" };
+      sentryTool.executeConfigTool(args);
+      assertFalse("The execution should have failed due to missing Sentry config file"
+          + " (or policy file) path",
+          sentryTool.executeConfigTool(args));
+    }
+
+    {
+      String[] args = { "-s", "1.8.0", "-p", "/test/path" };
+      sentryTool.executeConfigTool(args);
+      assertFalse("The execution should have failed due to missing Sentry config output file path",
+          sentryTool.executeConfigTool(args));
+    }
+
+    {
+      String[] args = { "-s", "1.8.0", "-c", "/test/path1", "-p", "/test/path2" };
+      sentryTool.executeConfigTool(args);
+      assertFalse("The execution should have failed due to providing both Sentry config file"
+          + " as well as policy file params",
+          sentryTool.executeConfigTool(args));
+    }
+  }
+
+  private void initializeSentryService() throws SentryUserException {
+    // Define an admin role
+    client.createRoleIfNotExist(requestorName, "admin_role", SOLR);
+    client.grantRoleToGroups(requestorName, "admin_role", SOLR, Sets.newHashSet("admin_group"));
+
+    // Define a developer role
+    client.createRoleIfNotExist(requestorName, "dev_role", SOLR);
+    client.grantRoleToGroups(requestorName, "dev_role", SOLR, Sets.newHashSet("dev_group"));
+
+    // Define a user role
+    client.createRoleIfNotExist(requestorName, "user_role", SOLR);
+    client.grantRoleToGroups(requestorName, "user_role", SOLR, Sets.newHashSet("user_group"));
+
+    // Grant permissions
+    client.grantPrivilege(requestorName, "admin_role", SOLR,
+        new TSentryPrivilege(SOLR, "service1",
+            Arrays.asList(new TAuthorizable("collection", "admin")), "*"));
+    client.grantPrivilege(requestorName, "dev_role", SOLR,
+        new TSentryPrivilege(SOLR, "service1",
+            Arrays.asList(new TAuthorizable("collection", "*")), "*"));
+    client.grantPrivilege(requestorName, "user_role", SOLR,
+        new TSentryPrivilege(SOLR, "service1",
+            Arrays.asList(new TAuthorizable("collection", "foo")), "*"));
+  }
+
+  private void verifySentryServiceState(Map<String, Set<String>> groupMapping,
+      Map<String, Set<String>> privilegeMapping) throws SentryUserException {
+    // check roles
+    Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
+    assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
+    Set<String> roles = new HashSet<String>();
+    for (TSentryRole tRole : tRoles) {
+      roles.add(tRole.getRoleName());
+    }
+
+    for (String expectedRole : groupMapping.keySet()) {
+      assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
+    }
+
+    // check groups
+    for (TSentryRole tRole : tRoles) {
+      Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
+      assertEquals("Group size doesn't match for role: " + tRole.getRoleName(),
+          expectedGroups.size(), tRole.getGroups().size());
+      assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
+          tRole.getGroups().containsAll(expectedGroups));
+    }
+
+    // check privileges
+    GenericPrivilegeConverter convert = new GenericPrivilegeConverter(SOLR, service);
+    for (String role : roles) {
+      Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+          requestorName, role, SOLR, service);
+      Set<String> expectedPrivileges = privilegeMapping.get(role);
+      assertEquals("Privilege set size doesn't match for role: " + role + " Actual permissions : " + privileges,
+          expectedPrivileges.size(), privileges.size());
+
+      Set<String> privilegeStrs = new HashSet<String>();
+      for (TSentryPrivilege privilege : privileges) {
+        privilegeStrs.add(convert.toString(privilege).toLowerCase());
+      }
+
+      for (String expectedPrivilege : expectedPrivileges) {
+        assertTrue("Did not find expected privilege: " + expectedPrivilege + " in " + privilegeStrs,
+            privilegeStrs.contains(expectedPrivilege));
+      }
+    }
+  }
+
+  private Path initializeSentryPolicyFile() throws Exception {
+    PolicyFile file = new PolicyFile();
+
+    file.addRolesToGroup("admin_group", "admin_role");
+    file.addRolesToGroup("dev_group", "dev_role");
+    file.addRolesToGroup("user_group", "user_role");
+
+    file.addPermissionsToRole("admin_role", "collection=admin->action=*");
+    file.addPermissionsToRole("dev_role", "collection=*->action=*");
+    file.addPermissionsToRole("user_role", "collection=foo->action=*");
+
+    Path policyFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider.ini");
+    file.write(policyFilePath.toFile());
+
+    return policyFilePath;
+  }
+
+  private void verifySentryPolicyFile (Set<String> groups, Map<String, Set<String>> privilegeMapping,
+      Path policyFilePath) throws IOException {
+    SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf,
+        new org.apache.hadoop.fs.Path(policyFilePath.toUri()));
+    policyFileBackend.initialize(new ProviderBackendContext());
+    Table<String, String, Set<String>> groupRolePrivilegeTable =
+        policyFileBackend.getGroupRolePrivilegeTable();
+
+    assertEquals(groups, groupRolePrivilegeTable.rowKeySet());
+    assertEquals(privilegeMapping.keySet(), groupRolePrivilegeTable.columnKeySet());
+
+    for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
+      for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+        if (groupRolePrivilegeTable.contains(groupName, roleName)) {
+          Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
+          assertEquals(privilegeMapping.get(roleName), privileges);
+        }
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java
new file mode 100644
index 0000000..40df736
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolIndexer.java
@@ -0,0 +1,263 @@
+ /**
+ * 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.sentry.cli.tools;
+
+ import com.google.common.collect.Sets;
+ import com.google.common.io.Files;
+ import org.apache.commons.io.FileUtils;
+ import org.apache.sentry.core.common.exception.SentryConfigurationException;
+ import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+ import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+ import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+ import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
+ import org.apache.sentry.service.thrift.ServiceConstants;
+ import org.junit.After;
+ import org.junit.Before;
+ import org.junit.Test;
+
+ import java.io.File;
+ import java.io.FileOutputStream;
+ import java.util.HashMap;
+ import java.util.HashSet;
+ import java.util.Map;
+ import java.util.Set;
+
+ import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
+ import static org.junit.Assert.assertEquals;
+ import static org.junit.Assert.assertTrue;
+ import static org.junit.Assert.fail;
+
+ public class TestSentryConfigToolIndexer extends SentryGenericServiceIntegrationBase {
+   private static String VALID_POLICY_INI = TestSentryConfigToolIndexer.class.getClassLoader().getResource("indexer_config_import_tool.ini").getPath() ;
+   private static String INVALID_POLICY_INI = TestSentryConfigToolIndexer.class.getClassLoader().getResource("indexer_invalid.ini").getPath();
+   private static String CASE_POLICY_INI = TestSentryConfigToolIndexer.class.getClassLoader().getResource("indexer_case.ini").getPath();
+   private File confDir;
+   private File confPath;
+   private String requestorName = "";
+   private String service = "service1";
+
+   @Before
+   public void prepareForTest() throws Exception {
+     confDir = Files.createTempDir();
+     confPath = new File(confDir, "sentry-site.xml");
+     conf.set(ServiceConstants.ClientConfig.SERVICE_NAME, service);
+     if (confPath.createNewFile()) {
+       FileOutputStream to = new FileOutputStream(confPath);
+       conf.writeXml(to);
+       to.close();
+     }
+     requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
+     Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+     setLocalGroupMapping(requestorName, requestorUserGroupNames);
+     // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+     setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+     writePolicyFile();
+   }
+
+   @After
+   public void clearTestData() throws Exception {
+     FileUtils.deleteQuietly(confDir);
+
+     // clear roles and privileges
+     Set<TSentryRole> tRoles = client.listAllRoles(requestorName, HBASE_INDEXER);
+     for (TSentryRole tRole : tRoles) {
+       String role = tRole.getRoleName();
+       Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+           requestorName, role, HBASE_INDEXER, service);
+       for (TSentryPrivilege privilege : privileges) {
+         client.revokePrivilege(requestorName, role, HBASE_INDEXER, privilege);
+       }
+       client.dropRole(requestorName, role, HBASE_INDEXER);
+     }
+   }
+
+   @Test
+   public void testConvertIni() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         String[] args = {"-mgr", "-f", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         sentryTool.executeShell(args);
+
+         Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+         groupMapping.put("corporal_role", Sets.newHashSet("corporal", "sergeant", "general", "commander_in_chief"));
+         groupMapping.put("sergeant_role", Sets.newHashSet("sergeant", "general", "commander_in_chief"));
+         groupMapping.put("general_role", Sets.newHashSet("general", "commander_in_chief"));
+         groupMapping.put("commander_in_chief_role", Sets.newHashSet("commander_in_chief"));
+
+
+         Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+         privilegeMapping.put("corporal_role",
+             Sets.newHashSet("Indexer=info->action=read", "Indexer=info->action=write"));
+         privilegeMapping.put("sergeant_role",
+             Sets.newHashSet("Indexer=info->action=write"));
+         privilegeMapping.put("general_role",
+             Sets.newHashSet("Indexer=info->action=*"));
+         privilegeMapping.put("commander_in_chief_role",
+             Sets.newHashSet("Indexer=*->action=*"));
+
+         // check roles
+         Set<TSentryRole> tRoles = client.listAllRoles(requestorName, HBASE_INDEXER);
+         assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
+         Set<String> roles = new HashSet<String>();
+         for (TSentryRole tRole : tRoles) {
+           roles.add(tRole.getRoleName());
+         }
+
+         for (String expectedRole : groupMapping.keySet()) {
+           assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
+         }
+
+         // check groups
+         for (TSentryRole tRole : tRoles) {
+           Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
+           assertEquals("Group size doesn't match for role: " + tRole.getRoleName(),
+               expectedGroups.size(), tRole.getGroups().size());
+           assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
+               tRole.getGroups().containsAll(expectedGroups));
+         }
+
+         // check privileges
+         GenericPrivilegeConverter convert = new GenericPrivilegeConverter(HBASE_INDEXER, service);
+         for (String role : roles) {
+           Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+               requestorName, role, HBASE_INDEXER, service);
+           Set<String> expectedPrivileges = privilegeMapping.get(role);
+           assertEquals("Privilege set size doesn't match for role: " + role,
+               expectedPrivileges.size(), privileges.size());
+
+           Set<String> privilegeStrs = new HashSet<String>();
+           for (TSentryPrivilege privilege : privileges) {
+             privilegeStrs.add(convert.toString(privilege));
+           }
+
+           for (String expectedPrivilege : expectedPrivileges) {
+             assertTrue("Did not find expected privilege: " + expectedPrivilege,
+                 privilegeStrs.contains(expectedPrivilege));
+           }
+         }
+       }
+     });
+   }
+
+   @Test
+   public void testNoPolicyFile() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         String[] args = { "-mgr", "-f", INVALID_POLICY_INI + "Foobar", "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         try {
+           sentryTool.executeShell(args);
+           fail("Exception should be thrown for nonexistant ini");
+         } catch (SentryConfigurationException e) {
+           // expected exception
+         }
+       }
+     });
+   }
+
+   @Test
+   public void testNoValidateNorImport() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         String[] args = { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath()};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         try {
+           sentryTool.executeShell(args);
+           fail("Exception should be thrown for validating invalid ini");
+         } catch (IllegalArgumentException e) {
+           // expected exception
+         }
+       }
+     });
+   }
+
+   @Test
+   public void testConvertInvalidIni() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         // test: validate an invalid ini
+         String[] args = { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         try {
+           sentryTool.executeShell(args);
+           fail("Exception should be thrown for validating invalid ini");
+         } catch (SentryConfigurationException e) {
+           // expected exception
+         }
+
+         // test without validating, should not error
+         args = new String[] { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i"};
+         sentryTool = new SentryShellIndexer();
+         sentryTool.executeShell(args);
+       }
+     });
+   }
+
+   @Test
+   public void testCompatCheck() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         // test: validate an invalid ini
+         String[] args = { "-mgr", "-f", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         try {
+           sentryTool.executeShell(args);
+           fail("Exception should be thrown for validating invalid ini");
+         } catch (SentryConfigurationException e) {
+           assertEquals("Expected error", 1, e.getConfigErrors().size());
+           String error = e.getConfigErrors().get(0);
+           assertCasedRoleNamesInMessage(error, "RoLe1", "rOlE1");
+           String warning = e.getConfigWarnings().get(0);
+           assertCasedRoleNamesInMessage(warning, "ROLE2", "RoLe1", "rOlE1");
+           assertEquals("Expected warning", 1, e.getConfigWarnings().size());
+         }
+
+         // test without compat checking
+         args = new String[] { "-mgr", "-f", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i", "-v"};
+         sentryTool = new SentryShellIndexer();
+         sentryTool.executeShell(args);
+       }
+     });
+   }
+
+   // Test that a valid compat check doesn't throw an exception
+   @Test
+   public void testCompatCheckValid() throws Exception {
+     runTestAsSubject(new TestOperation() {
+       @Override
+       public void runTestAsSubject() throws Exception {
+         String[] args = { "-mgr", "-f", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
+         SentryShellIndexer sentryTool = new SentryShellIndexer();
+         sentryTool.executeShell(args);
+       }
+     });
+   }
+
+   private void assertCasedRoleNamesInMessage(String message, String ... casedRoleNames) {
+     for (String casedRoleName : casedRoleNames) {
+       assertTrue("Expected cased role name: " + casedRoleName, message.contains(casedRoleName));
+     }
+   }
+ }

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java
new file mode 100644
index 0000000..292521d
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryConfigToolSolr.java
@@ -0,0 +1,260 @@
+ /**
+ * 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.sentry.cli.tools;
+
+import com.google.common.io.Files;
+import com.google.common.collect.Sets;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.core.common.exception.SentryConfigurationException;
+
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestSentryConfigToolSolr extends SentryGenericServiceIntegrationBase {
+  private static String VALID_POLICY_INI = TestSentryConfigToolSolr.class.getClassLoader().getResource("solr_config_import_tool.ini").getPath();
+  private static String INVALID_POLICY_INI = TestSentryConfigToolSolr.class.getClassLoader().getResource("solr_invalid.ini").getPath();
+  private static String CASE_POLICY_INI = TestSentryConfigToolSolr.class.getClassLoader().getResource("solr_case.ini").getPath();
+  private File confDir;
+  private File confPath;
+  private String requestorName = "";
+  private String service = "service1";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+
+    // clear roles and privileges
+    Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
+    for (TSentryRole tRole : tRoles) {
+      String role = tRole.getRoleName();
+      Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+          requestorName, role, SOLR, service);
+      for (TSentryPrivilege privilege : privileges) {
+        client.revokePrivilege(requestorName, role, SOLR, privilege);
+      }
+      client.dropRole(requestorName, role, SOLR);
+    }
+  }
+
+  @Test
+  public void testConvertIni() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        sentryTool.executeConfigTool(args);
+
+        Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
+        groupMapping.put("corporal_role", Sets.newHashSet("corporal", "sergeant", "general", "commander_in_chief"));
+        groupMapping.put("sergeant_role", Sets.newHashSet("sergeant", "general", "commander_in_chief"));
+        groupMapping.put("general_role", Sets.newHashSet("general", "commander_in_chief"));
+        groupMapping.put("commander_in_chief_role", Sets.newHashSet("commander_in_chief"));
+
+        Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
+        privilegeMapping.put("corporal_role",
+            Sets.newHashSet("Collection=info->action=query", "Collection=info->action=update"));
+        privilegeMapping.put("sergeant_role",
+            Sets.newHashSet("Collection=info->action=update"));
+        privilegeMapping.put("general_role",
+            Sets.newHashSet("Collection=info->action=*"));
+        privilegeMapping.put("commander_in_chief_role",
+            Sets.newHashSet("Collection=*->action=*"));
+
+        // check roles
+        Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
+        assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
+        Set<String> roles = new HashSet<String>();
+        for (TSentryRole tRole : tRoles) {
+          roles.add(tRole.getRoleName());
+        }
+
+        for (String expectedRole : groupMapping.keySet()) {
+          assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
+        }
+
+        // check groups
+        for (TSentryRole tRole : tRoles) {
+          Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
+          assertEquals("Group size doesn't match for role: " + tRole.getRoleName(),
+              expectedGroups.size(), tRole.getGroups().size());
+          assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
+              tRole.getGroups().containsAll(expectedGroups));
+        }
+
+        // check privileges
+        GenericPrivilegeConverter convert = new GenericPrivilegeConverter(SOLR, service);
+        for (String role : roles) {
+          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
+              requestorName, role, SOLR, service);
+          Set<String> expectedPrivileges = privilegeMapping.get(role);
+          assertEquals("Privilege set size doesn't match for role: " + role,
+              expectedPrivileges.size(), privileges.size());
+
+          Set<String> privilegeStrs = new HashSet<String>();
+          for (TSentryPrivilege privilege : privileges) {
+            privilegeStrs.add(convert.toString(privilege));
+          }
+
+          for (String expectedPrivilege : expectedPrivileges) {
+            assertTrue("Did not find expected privilege: " + expectedPrivilege + " in " + privilegeStrs,
+                privilegeStrs.contains(expectedPrivilege));
+          }
+        }
+      }
+    });
+  }
+
+  @Test
+  public void testNoPolicyFile() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String[] args = { "-p", INVALID_POLICY_INI + "Foobar", "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        try {
+          sentryTool.executeConfigTool(args);
+          fail("Exception should be thrown for nonexistant ini");
+        } catch (SentryConfigurationException e) {
+          // expected exception
+        }
+      }
+    });
+  }
+
+  @Test
+  public void testNoValidateNorImport() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath()};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        try {
+          sentryTool.executeConfigTool(args);
+          fail("Exception should be thrown for validating invalid ini");
+        } catch (IllegalArgumentException e) {
+          // expected exception
+        }
+      }
+    });
+  }
+
+  @Test
+  public void testConvertInvalidIni() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: validate an invalid ini
+        String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        try {
+          sentryTool.executeConfigTool(args);
+          fail("Exception should be thrown for validating invalid ini");
+        } catch (SentryConfigurationException e) {
+          // expected exception
+        }
+
+        // test without validating, should not error
+        args = new String[] { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i"};
+        sentryTool = new SentryConfigToolSolr();
+        sentryTool.executeConfigTool(args);
+      }
+    });
+  }
+
+  @Test
+  public void testCompatCheck() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: validate an invalid ini
+        String[] args = { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        try {
+          sentryTool.executeConfigTool(args);
+          fail("Exception should be thrown for validating invalid ini");
+        } catch (SentryConfigurationException e) {
+          assertEquals("Expected error", 1, e.getConfigErrors().size());
+          String error = e.getConfigErrors().get(0);
+          assertCasedRoleNamesInMessage(error, "RoLe1", "rOlE1");
+          String warning = e.getConfigWarnings().get(0);
+          assertCasedRoleNamesInMessage(warning, "ROLE2", "RoLe1", "rOlE1");
+          assertEquals("Expected warning", 1, e.getConfigWarnings().size());
+        }
+
+        // test without compat checking
+        args = new String[] { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i", "-v"};
+        sentryTool = new SentryConfigToolSolr();
+        sentryTool.executeConfigTool(args);
+      }
+    });
+  }
+
+  // Test that a valid compat check doesn't throw an exception
+  @Test
+  public void testCompatCheckValid() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
+        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
+        sentryTool.executeConfigTool(args);
+      }
+    });
+  }
+
+  private void assertCasedRoleNamesInMessage(String message, String ... casedRoleNames) {
+    for (String casedRoleName : casedRoleNames) {
+      assertTrue("Expected cased role name: " + casedRoleName, message.contains(casedRoleName));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java
new file mode 100644
index 0000000..657a8fe
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentrySchemaTool.java
@@ -0,0 +1,113 @@
+/**
+ * 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.sentry.cli.tools;
+
+import java.io.File;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.service.persistent.SentryStoreSchemaInfo;
+import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Files;
+
+public class TestSentrySchemaTool {
+  private Configuration sentryConf;
+  private SentrySchemaTool schemaTool;
+
+  private static final String OLDEST_INIT_VERSION = "1.4.0";
+  private static final String sentry_db_resources = findSentryProviderDBDir()+"/sentry-provider/sentry-provider-db/src/main/resources";
+
+  @Before
+  public void defaultSetup() throws Exception {
+    System.out.println(System.getProperty("user.dir"));
+    sentryConf = new Configuration();
+    File dbDir = new File(Files.createTempDir(), "sentry_policy_db");
+    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_URL,
+        "jdbc:derby:;databaseName=" + dbDir.getPath() + ";create=true");
+    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy");
+    schemaTool = new SentrySchemaTool(sentry_db_resources, sentryConf,
+        "derby");
+  }
+
+  private void nonDefaultsetup() throws Exception {
+    System.out.println(System.getProperty("user.dir"));
+    sentryConf = new Configuration();
+    File dbDir = new File(Files.createTempDir(), "sentry_policy_db");
+    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_URL,
+        "jdbc:derby:;databaseName=" + dbDir.getPath() + ";create=true");
+    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy");
+    schemaTool = new SentrySchemaTool(sentry_db_resources, sentryConf,
+        "derby");
+  }
+
+  /**This is a pretty ugly hack.  Since the derby files are in sentry-provider-db,
+   * we need to go back a few directories to get to it.  Running in Intellij defaults
+   * to the root dir of the project, while running the unit tests on the command line
+   * defaults to the root/sentry-tools dir.  Using the .class.getResource() defaults to
+   * the target/test-classes/blah dir.  So that's not usable.
+   *
+   * @return
+   */
+  private static String findSentryProviderDBDir() {
+
+    String pathToSentryProject = System.getProperty("user.dir");
+    if(pathToSentryProject.endsWith("/sentry-tools")) {
+      return pathToSentryProject.substring(0, pathToSentryProject.length()- "/sentry-tools".length());
+    }
+    return pathToSentryProject;
+  }
+  @Test
+  public void testInitNonDefault() throws Exception {
+    nonDefaultsetup();
+    schemaTool.doInit();
+    schemaTool.verifySchemaVersion();
+  }
+
+  @Test
+  public void testInit() throws Exception {
+    schemaTool.doInit();
+    schemaTool.verifySchemaVersion();
+  }
+
+  @Test
+  public void testInitTo() throws Exception {
+    schemaTool.doInit(SentryStoreSchemaInfo.getSentryVersion());
+    schemaTool.verifySchemaVersion();
+  }
+
+  @Test(expected = SentryUserException.class)
+  public void testDryRun() throws Exception {
+    schemaTool.setDryRun(true);
+    schemaTool.doInit();
+    schemaTool.setDryRun(false);
+    // verification should fail since dryRun didn't create the actual schema
+    schemaTool.verifySchemaVersion();
+  }
+
+  @Test
+  public void testUpgrade() throws Exception {
+    schemaTool.doInit(OLDEST_INIT_VERSION);
+    schemaTool.doUpgrade();
+    schemaTool.verifySchemaVersion();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java
new file mode 100644
index 0000000..46dc436
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellHive.java
@@ -0,0 +1,613 @@
+/**
+ * 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.sentry.cli.tools;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+import org.apache.sentry.service.thrift.SentryServiceIntegrationBase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+
+public class TestSentryShellHive extends SentryServiceIntegrationBase {
+
+  private File confDir;
+  private File confPath;
+  private static String TEST_ROLE_NAME_1 = "testRole1";
+  private static String TEST_ROLE_NAME_2 = "testRole2";
+  private String requestorName = "";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+  }
+
+  @Test
+  public void testCreateDropRole() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: create role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: create role with --create_role
+        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // validate the result, list roles with -lr
+        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // validate the result, list roles with --list_role
+        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // test: drop role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: drop role with --drop_role
+        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listAllRoles(requestorName);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+      }
+    });
+  }
+
+  @Test
+  public void testAddDeleteRoleForGroup() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        client.createRole(requestorName, TEST_ROLE_NAME_2);
+        // test: add role to group with -arg
+        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: add role to multiple groups
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup2,testGroup3",
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: add role to group with --add_role_group
+        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1",
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // validate the result list roles with -lr and -g
+        args = new String[] { "-lr", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+
+        // list roles with --list_role and -g
+        args = new String[] { "--list_role", "-g", "testGroup2", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        args = new String[] { "--list_role", "-g", "testGroup3", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // List the groups and roles via listGroups
+        args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath()};
+        sentryShell = new SentryShellHive();
+        Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true);
+        assertEquals(3, groups.size());
+        assertTrue(groups.contains("testGroup3 = testrole1"));
+        assertTrue(groups.contains("testGroup2 = testrole1"));
+        assertTrue(groups.contains("testGroup1 = testrole2, testrole1"));
+
+        // test: delete role from group with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: delete role to multiple groups
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup2,testGroup3",
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        // test: delete role from group with --delete_role_group
+        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, "testGroup1");
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, "testGroup2");
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, "testGroup3");
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2);
+      }
+    });
+  }
+
+  @Test
+  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        client.createRole(requestorName, TEST_ROLE_NAME_2);
+
+        // test: grant privilege to role with -gpr
+        String[] args = { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->action=*",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // test the list privilege with -lp
+        args = new String[] { "-lp", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+        // validate the result for -lp
+        assertEquals("Incorrect number of privileges", 6, privilegeStrs.size());
+        assertTrue(privilegeStrs.contains("server=server1->action=*"));
+        assertTrue(privilegeStrs.contains("server=server1->db=db1->action=select"));
+        assertTrue(privilegeStrs.contains("server=server1->db=db1->table=tbl1->action=insert"));
+        assertTrue(privilegeStrs
+            .contains("server=server1->db=db1->table=tbl1->column=col1->action=insert"));
+        assertTrue(privilegeStrs
+            .contains("server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true"));
+        assertTrue(privilegeStrs.contains("server=server1->uri=hdfs://path/testuri->action=*"));
+
+        // test: revoke privilege from role with -rpr
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+            TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 5, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 4, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 3, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 2, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 1, privileges.size());
+
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p", "server=server1->action=*",
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 0, privileges.size());
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2);
+      }
+    });
+  }
+
+  @Test
+  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        client.createRole(requestorName, TEST_ROLE_NAME_2);
+
+        // test: grant privilege to role with -gpr
+        String[] args = { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+
+        // test the list privilege with -lp
+        args = new String[] { "--list_privilege", "-r", TEST_ROLE_NAME_1, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+        // validate the result for -lp
+        assertEquals("Incorrect number of privileges", 6, privilegeStrs.size());
+        assertTrue(privilegeStrs.contains("server=server1->action=*"));
+        assertTrue(privilegeStrs.contains("server=server1->db=db1->action=select"));
+        assertTrue(privilegeStrs.contains("server=server1->db=db1->table=tbl1->action=insert"));
+        assertTrue(privilegeStrs
+            .contains("server=server1->db=db1->table=tbl1->column=col1->action=insert"));
+        assertTrue(privilegeStrs
+            .contains("server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true"));
+        assertTrue(privilegeStrs.contains("server=server1->uri=hdfs://path/testuri->action=*"));
+
+        // test: revoke privilege from role with -rpr
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+            TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 5, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 4, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 3, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 2, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 1, privileges.size());
+
+        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->action=*", "-conf", confPath.getAbsolutePath() };
+        SentryShellHive.main(args);
+        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
+        assertEquals("Incorrect number of privileges", 0, privileges.size());
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2);
+      }
+    });
+  }
+
+  @Test
+  public void testNegativeCaseWithInvalidArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        // test: create duplicate role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellHive sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for creating duplicate role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: drop non-exist role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for dropping non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: add non-exist role to group with -arg
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for granting non-exist role to group");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: drop group from non-exist role with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for drop group from non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: grant privilege to role with the error privilege format
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=*",
+            "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // excepted exception
+        }
+
+        // test: grant privilege to role with the error privilege hierarchy
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->table=tbl1->column=col2->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // excepted exception
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+      }
+    });
+  }
+
+  @Test
+  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String strOptionConf = "conf";
+        client.createRole(requestorName, TEST_ROLE_NAME_1);
+        // test: the conf is required argument
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1 };
+        SentryShellHive sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
+
+        // test: -r is required when create role
+        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when drop role
+        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when add role to group
+        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when add role to group
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when delete role from group
+        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when delete role from group
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when grant privilege to role
+        args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when grant privilege to role
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: -r is required when revoke privilege from role
+        args = new String[] { "-rpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when revoke privilege from role
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: command option is required for shell
+        args = new String[] {"-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellHive();
+        validateMissingParameterMsgsContains(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
+                "-arg Add role to group",
+                "-cr Create role",
+                "-rpr Revoke privilege from role",
+                "-drg Delete role from group",
+                "-lr List role",
+                "-lp List privilege",
+                "-gpr Grant privilege to role",
+                "-dr Drop role");
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1);
+      }
+    });
+  }
+
+  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+  private Set<String> getShellResultWithOSRedirect(SentryShellHive sentryShell,
+      String[] args, boolean exceptedExecuteResult) throws Exception {
+    PrintStream oldOut = System.out;
+    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+    System.setOut(new PrintStream(outContent));
+    assertEquals(exceptedExecuteResult, sentryShell.executeShell(args));
+    Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n"));
+    System.setOut(oldOut);
+    return resultSet;
+  }
+
+  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
+    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
+      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
+          expectedRoleNames.length, roleNames.size());
+      Set<String> lowerCaseRoles = new HashSet<String>();
+      for (String role : roleNames) {
+        lowerCaseRoles.add(role.toLowerCase());
+      }
+
+      for (String expectedRole : expectedRoleNames) {
+        assertTrue("Expected role: " + expectedRole,
+            lowerCaseRoles.contains(expectedRole.toLowerCase()));
+      }
+    }
+  }
+
+  private void validateMissingParameterMsg(SentryShellHive sentryShell, String[] args,
+      String exceptedErrorMsg) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    assertTrue(errorMsgs.contains(exceptedErrorMsg));
+  }
+
+  private void validateMissingParameterMsgsContains(SentryShellHive sentryShell, String[] args,
+      String ... expectedErrorMsgsContains) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    boolean foundAllMessages = false;
+    Iterator<String> it = errorMsgs.iterator();
+    while (it.hasNext()) {
+      String errorMessage = it.next();
+      boolean missingExpected = false;
+      for (String expectedContains : expectedErrorMsgsContains) {
+        if (!errorMessage.contains(expectedContains)) {
+          missingExpected = true;
+          break;
+        }
+      }
+      if (!missingExpected) {
+        foundAllMessages = true;
+        break;
+      }
+    }
+    assertTrue(foundAllMessages);
+  }
+}


[9/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.

Posted by co...@apache.org.
SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.


Project: http://git-wip-us.apache.org/repos/asf/sentry/repo
Commit: http://git-wip-us.apache.org/repos/asf/sentry/commit/6752f14a
Tree: http://git-wip-us.apache.org/repos/asf/sentry/tree/6752f14a
Diff: http://git-wip-us.apache.org/repos/asf/sentry/diff/6752f14a

Branch: refs/heads/master
Commit: 6752f14aafad2f9ead0198f2f840db120182b268
Parents: 0668237
Author: Colm O hEigeartaigh <co...@apache.org>
Authored: Mon Apr 30 17:34:56 2018 +0100
Committer: Colm O hEigeartaigh <co...@apache.org>
Committed: Mon Apr 30 17:35:33 2018 +0100

----------------------------------------------------------------------
 bin/sentryShell                                 |  10 +-
 pom.xml                                         |   2 +-
 sentry-provider/sentry-provider-db/pom.xml      |  13 +
 .../generic/SentryGenericProviderBackend.java   |   2 +-
 .../provider/db/generic/UpdatableCache.java     |   2 +-
 .../tools/GenericPrivilegeConverter.java        |   6 +-
 .../tools/PermissionsMigrationToolCommon.java   | 348 -----------
 .../tools/PermissionsMigrationToolSolr.java     | 109 ----
 .../generic/tools/SentryConfigToolCommon.java   | 152 -----
 .../generic/tools/SentryConfigToolIndexer.java  | 340 ----------
 .../db/generic/tools/SentryConfigToolSolr.java  | 264 --------
 .../db/generic/tools/SentryShellGeneric.java    | 158 -----
 .../db/generic/tools/SentryShellIndexer.java    | 124 ----
 .../tools/TSentryPrivilegeConverter.java        |  35 ++
 .../tools/command/GenericShellCommand.java      | 155 -----
 .../command/TSentryPrivilegeConverter.java      |  34 -
 .../provider/db/tools/SentrySchemaHelper.java   | 315 ----------
 .../provider/db/tools/SentrySchemaTool.java     | 595 ------------------
 .../provider/db/tools/SentryShellCommon.java    | 284 ---------
 .../provider/db/tools/SentryShellHive.java      | 118 ----
 .../sentry/provider/db/tools/ShellCommand.java  |  47 --
 .../db/tools/command/hive/CommandUtil.java      |  63 --
 .../db/tools/command/hive/HiveShellCommand.java | 152 -----
 .../tools/TestPermissionsMigrationToolSolr.java | 362 -----------
 .../tools/TestSentryConfigToolIndexer.java      | 263 --------
 .../generic/tools/TestSentryConfigToolSolr.java | 261 --------
 .../generic/tools/TestSentryShellIndexer.java   | 526 ----------------
 .../db/generic/tools/TestSentryShellKafka.java  | 550 -----------------
 .../db/generic/tools/TestSentryShellSolr.java   | 534 ----------------
 .../db/generic/tools/TestSentryShellSqoop.java  | 532 ----------------
 .../provider/db/tools/TestSentrySchemaTool.java |  94 ---
 .../provider/db/tools/TestSentryShellHive.java  | 613 -------------------
 .../src/test/resources/indexer_case.ini         |  26 -
 .../resources/indexer_config_import_tool.ini    |  29 -
 .../src/test/resources/indexer_invalid.ini      |  21 -
 .../src/test/resources/solr_case.ini            |  26 -
 .../test/resources/solr_config_import_tool.ini  |  29 -
 .../src/test/resources/solr_invalid.ini         |  21 -
 sentry-tools/pom.xml                            |  44 +-
 .../main/java/org/apache/sentry/SentryMain.java |   2 +-
 .../tools/PermissionsMigrationToolCommon.java   | 349 +++++++++++
 .../cli/tools/PermissionsMigrationToolSolr.java | 109 ++++
 .../cli/tools/SentryConfigToolCommon.java       | 152 +++++
 .../cli/tools/SentryConfigToolIndexer.java      | 341 +++++++++++
 .../sentry/cli/tools/SentryConfigToolSolr.java  | 265 ++++++++
 .../sentry/cli/tools/SentrySchemaHelper.java    | 315 ++++++++++
 .../sentry/cli/tools/SentrySchemaTool.java      | 595 ++++++++++++++++++
 .../sentry/cli/tools/SentryShellCommon.java     | 284 +++++++++
 .../sentry/cli/tools/SentryShellGeneric.java    | 157 +++++
 .../sentry/cli/tools/SentryShellHive.java       | 118 ++++
 .../sentry/cli/tools/SentryShellIndexer.java    | 124 ++++
 .../apache/sentry/cli/tools/ShellCommand.java   |  47 ++
 .../cli/tools/command/GenericShellCommand.java  | 156 +++++
 .../cli/tools/command/hive/CommandUtil.java     |  63 ++
 .../tools/command/hive/HiveShellCommand.java    | 152 +++++
 .../org/apache/sentry/shell/GroupShell.java     |   2 +-
 .../org/apache/sentry/shell/PrivsShell.java     |   2 +-
 .../org/apache/sentry/shell/RolesShell.java     |   2 +-
 .../org/apache/sentry/shell/TopLevelShell.java  |   8 +-
 .../tools/TestPermissionsMigrationToolSolr.java | 362 +++++++++++
 .../cli/tools/TestSentryConfigToolIndexer.java  | 263 ++++++++
 .../cli/tools/TestSentryConfigToolSolr.java     | 260 ++++++++
 .../sentry/cli/tools/TestSentrySchemaTool.java  | 113 ++++
 .../sentry/cli/tools/TestSentryShellHive.java   | 613 +++++++++++++++++++
 .../cli/tools/TestSentryShellIndexer.java       | 525 ++++++++++++++++
 .../sentry/cli/tools/TestSentryShellKafka.java  | 549 +++++++++++++++++
 .../sentry/cli/tools/TestSentryShellSolr.java   | 533 ++++++++++++++++
 .../sentry/cli/tools/TestSentryShellSqoop.java  | 531 ++++++++++++++++
 sentry-tools/src/test/resources/cacerts.jks     | Bin 0 -> 954 bytes
 .../src/test/resources/indexer_case.ini         |  26 +
 .../resources/indexer_config_import_tool.ini    |  29 +
 .../src/test/resources/indexer_invalid.ini      |  21 +
 sentry-tools/src/test/resources/keystore.jks    | Bin 0 -> 2245 bytes
 .../src/test/resources/log4j.properties         |  34 +
 sentry-tools/src/test/resources/solr_case.ini   |  26 +
 .../test/resources/solr_config_import_tool.ini  |  29 +
 .../src/test/resources/solr_invalid.ini         |  21 +
 77 files changed, 7266 insertions(+), 7171 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/bin/sentryShell
----------------------------------------------------------------------
diff --git a/bin/sentryShell b/bin/sentryShell
index 17b1429..140f7ce 100755
--- a/bin/sentryShell
+++ b/bin/sentryShell
@@ -54,15 +54,15 @@ for f in ${SENTRY_HOME}/lib/plugins/*.jar; do
 done
 
 args=()
-shell=org.apache.sentry.provider.db.tools.SentryShellHive
+shell=org.apache.sentry.cli.tools.SentryShellHive
 # get the type argument for the command
 while [ $# -gt 0 ]; do    # Until you run out of parameters . . .
   if [[ "$1" = "-t" || "$1" = "--type" ]]; then
     case $2 in
-      "hive") shell=org.apache.sentry.provider.db.tools.SentryShellHive ;;
-      "kafka") shell=org.apache.sentry.provider.db.generic.tools.SentryShellGeneric ;;
-      "solr") shell=org.apache.sentry.provider.db.generic.tools.SentryShellGeneric ;;
-      "sqoop") shell=org.apache.sentry.provider.db.generic.tools.SentryShellGeneric ;;
+      "hive") shell=org.apache.sentry.cli.tools.SentryShellHive ;;
+      "kafka") shell=org.apache.sentry.cli.tools.SentryShellGeneric ;;
+      "solr") shell=org.apache.sentry.cli.tools.SentryShellGeneric ;;
+      "sqoop") shell=org.apache.sentry.cli.tools.SentryShellGeneric ;;
       *) echo "Doesn't support the type $2!"; exit 1 ;;
     esac
   fi

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 16a3838..262a9d8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1048,7 +1048,7 @@ limitations under the License.
                 <exclude>%regex[org.apache.sentry.provider.db.service.thrift.*.class]</exclude>
                 <exclude>%regex[org.apache.solr.handler.admin.*.class]</exclude>
                 <exclude>%regex[org.apache.sentry.provider.db.generic.service.thrift.*.class]</exclude>
-                <exclude>%regex[org.apache.sentry.provider.db.generic.tools.*.class]</exclude>
+                <exclude>%regex[org.apache.sentry.cli.tools.*.class]</exclude>
               </excludes>
             </configuration>
           </plugin>

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/pom.xml b/sentry-provider/sentry-provider-db/pom.xml
index b8cccfa..369e262 100644
--- a/sentry-provider/sentry-provider-db/pom.xml
+++ b/sentry-provider/sentry-provider-db/pom.xml
@@ -398,6 +398,19 @@ limitations under the License.
           </execution>
         </executions>
       </plugin>
+      <!--This is to export SentryGenericServiceIntegrationBase across Modules -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <version>2.2</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>test-jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
     <pluginManagement>
       <plugins>

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java
index cf552b1..fe0eb07 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/SentryGenericProviderBackend.java
@@ -35,7 +35,7 @@ import org.apache.sentry.provider.common.ProviderBackendContext;
 import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
 import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
 import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
 import org.apache.sentry.service.thrift.ServiceConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java
index edf0934..31fcfc7 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/UpdatableCache.java
@@ -18,7 +18,7 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.security.UserGroupInformation;
 import org.apache.sentry.provider.common.TableCache;
 import org.apache.sentry.provider.db.generic.service.thrift.*;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
+import org.apache.sentry.provider.db.generic.tools.TSentryPrivilegeConverter;
 import org.apache.sentry.service.thrift.ServiceConstants;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java
index 8de543c..82b21ef 100644
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/GenericPrivilegeConverter.java
@@ -1,4 +1,5 @@
-/**
+/*
+ *
  * 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
@@ -7,7 +8,7 @@
  * "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
+ *      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,
@@ -48,7 +49,6 @@ import org.apache.sentry.provider.common.AuthorizationComponent;
 import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable;
 import org.apache.sentry.provider.db.generic.service.thrift.TSentryGrantOption;
 import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
 import org.apache.shiro.config.ConfigurationException;
 
 /**

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolCommon.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolCommon.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolCommon.java
deleted file mode 100644
index e3d81f8..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolCommon.java
+++ /dev/null
@@ -1,348 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Optional;
-import java.util.Set;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.Parser;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.core.common.ActiveRoleSet;
-import org.apache.sentry.core.common.utils.PolicyFileConstants;
-import org.apache.sentry.core.common.utils.PolicyFiles;
-import org.apache.sentry.core.common.utils.Version;
-import org.apache.sentry.policy.common.PrivilegeUtils;
-import org.apache.sentry.provider.common.ProviderBackendContext;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.file.SimpleFileProviderBackend;
-import org.apache.shiro.config.Ini;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
-
-/**
- * This class provides basic framework required to migrate permissions between different Sentry
- * versions. Individual components (e.g. SOLR, KAFKA) needs to override the this class
- * to provide component specific migration functionality.
- */
-public abstract class PermissionsMigrationToolCommon {
-  private static final Logger LOGGER = LoggerFactory.getLogger(PermissionsMigrationToolCommon.class);
-  public static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
-
-  private Version sourceVersion;
-  private Optional<String> confPath = Optional.empty();
-  private Optional<String> policyFile = Optional.empty();
-  private Optional<String> outputFile = Optional.empty();
-  private boolean dryRun = false;
-
-  /**
-   * @return version of Sentry for which the privileges need to be migrated.
-   */
-  public final Version getSourceVersion() {
-    return sourceVersion;
-  }
-
-  /**
-   * This method returns the name of the component for the migration purpose.
-   * @param conf The Sentry configuration
-   * @return the name of the component
-   */
-  protected abstract String getComponent(Configuration conf);
-
-
-  /**
-   * This method returns the name of the service name for the migration purpose.
-   *
-   * @param conf The Sentry configuration
-   * @return the name of the service
-   */
-  protected abstract String getServiceName(Configuration conf);
-
-  /**
-   * Migrate the privileges specified via <code>privileges</code>.
-   *
-   * @param privileges A collection of privileges to be migrated.
-   * @return A collection of migrated privileges
-   *         An empty collection if migration is not necessary for the specified privileges.
-   */
-  protected abstract Collection<String> transformPrivileges (Collection<String> privileges);
-
-  /**
-   *  parse arguments
-   * <pre>
-   *   -s,--source                   Sentry source version
-   *   -c,--sentry_conf <filepath>   sentry config file path
-   *   -p --policy_file <filepath>   sentry (source) policy file path
-   *   -o --output      <filepath>   sentry (target) policy file path
-   *   -d --dry_run                  provides the output the migration for inspection without
-   *                                 making any configuration changes.
-   *   -h,--help                     print usage
-   * </pre>
-   * @param args
-   */
-  protected boolean parseArgs(String [] args) {
-    Options options = new Options();
-
-    Option sourceVersionOpt = new Option("s", "source", true, "Source Sentry version");
-    sourceVersionOpt.setRequired(true);
-    options.addOption(sourceVersionOpt);
-
-    Option sentryConfPathOpt = new Option("c", "sentry_conf", true,
-        "sentry-site.xml file path (only required in case of Sentry service)");
-    sentryConfPathOpt.setRequired(false);
-    options.addOption(sentryConfPathOpt);
-
-    Option sentryPolicyFileOpt = new Option("p", "policy_file", true,
-        "sentry (source) policy file path (only in case of file based Sentry configuration)");
-    sentryPolicyFileOpt.setRequired(false);
-    options.addOption(sentryPolicyFileOpt);
-
-    Option sentryOutputFileOpt = new Option("o", "output", true,
-        "sentry (target) policy file path (only in case of file based Sentry configuration)");
-    sentryOutputFileOpt.setRequired(false);
-    options.addOption(sentryOutputFileOpt);
-
-    Option dryRunOpt = new Option("d", "dry_run", false,
-        "provides the output the migration for inspection without making actual configuration changes");
-    dryRunOpt.setRequired(false);
-    options.addOption(dryRunOpt);
-
-    // help option
-    Option helpOpt = new Option("h", "help", false, "Shell usage");
-    helpOpt.setRequired(false);
-    options.addOption(helpOpt);
-
-    // this Option is parsed first for help option
-    Options helpOptions = new Options();
-    helpOptions.addOption(helpOpt);
-
-    try {
-      Parser parser = new GnuParser();
-
-      // parse help option first
-      CommandLine cmd = parser.parse(helpOptions, args, true);
-      for (Option opt : cmd.getOptions()) {
-        if (opt.getOpt().equals("h")) {
-          // get the help option, print the usage and exit
-          usage(options);
-          return false;
-        }
-      }
-
-      // without help option
-      cmd = parser.parse(options, args);
-
-      String sourceVersionStr = null;
-
-      for (Option opt : cmd.getOptions()) {
-        if (opt.getOpt().equals("s")) {
-          sourceVersionStr = opt.getValue();
-        } else if (opt.getOpt().equals("c")) {
-          confPath = Optional.of(opt.getValue());
-        } else if (opt.getOpt().equals("p")) {
-          policyFile = Optional.of(opt.getValue());
-        }  else if (opt.getOpt().equals("o")) {
-          outputFile = Optional.of(opt.getValue());
-        }  else if (opt.getOpt().equals("d")) {
-          dryRun = true;
-        }
-      }
-
-      sourceVersion = Version.parse(sourceVersionStr);
-
-      if (!(confPath.isPresent() || policyFile.isPresent())) {
-        System.out.println("Please select either file-based Sentry configuration (-p and -o flags)"
-            + " or Sentry service (-c flag) for migration.");
-        usage(options);
-        return false;
-      }
-
-      if (confPath.isPresent() && (policyFile.isPresent() || outputFile.isPresent())) {
-        System.out.println("In order to migrate service based Sentry configuration,"
-            + " do not specify either -p or -o parameters");
-        usage(options);
-        return false;
-      }
-
-      if (!confPath.isPresent() && (policyFile.isPresent() ^ outputFile.isPresent())) {
-        System.out.println("In order to migrate file based Sentry configuration,"
-            + " please make sure to specify both -p and -o parameters.");
-        usage(options);
-        return false;
-      }
-
-    } catch (ParseException | java.text.ParseException pe) {
-      System.out.println(pe.getMessage());
-      usage(options);
-      return false;
-    }
-    return true;
-  }
-
-  // print usage
-  private void usage(Options sentryOptions) {
-    HelpFormatter formatter = new HelpFormatter();
-    formatter.printHelp("sentryMigrationTool", sentryOptions);
-  }
-
-  public void run() throws Exception {
-    if (policyFile.isPresent()) {
-      migratePolicyFile();
-    } else {
-      migrateSentryServiceConfig();
-    }
-  }
-
-  private void migrateSentryServiceConfig() throws Exception {
-    Configuration conf = getSentryConf();
-    String component = getComponent(conf);
-    String serviceName = getServiceName(conf);
-    GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, serviceName, false);
-
-    // instantiate a client for sentry service.  This sets the ugi, so must
-    // be done before getting the ugi below.
-    try(SentryGenericServiceClient client =
-                SentryGenericServiceClientFactory.create(getSentryConf())) {
-      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
-      String requestorName = ugi.getShortUserName();
-
-      for (TSentryRole r : client.listAllRoles(requestorName, component)) {
-        for (TSentryPrivilege p : client.listAllPrivilegesByRoleName(requestorName,
-            r.getRoleName(), component, serviceName)) {
-
-          String privilegeStr = converter.toString(p);
-          Collection<String> privileges = Collections.singleton(privilegeStr);
-          Collection<String> migrated = transformPrivileges(privileges);
-          if (!migrated.isEmpty()) {
-            LOGGER.info("{} For role {} migrating privileges from {} to {}", getDryRunMessage(), r.getRoleName(),
-                privileges, migrated);
-
-            /*
-             * Note that it is not possible to provide transactional (all-or-nothing) behavior for these configuration
-             * changes since the Sentry client/server protocol does not support. e.g. under certain failure conditions
-             * like crash of Sentry server or network disconnect between client/server, it is possible that the migration
-             * can not complete but can also not be rolled back. Hence this migration tool relies on the fact that privilege
-             * grant/revoke operations are idempotent and hence re-execution of the migration tool will fix any inconsistency
-             * due to such failures.
-             **/
-            boolean originalPermPresent = false;
-            for (String perm : migrated) {
-              if (perm.equalsIgnoreCase(privilegeStr)) {
-                originalPermPresent = true;
-                continue;
-              }
-              TSentryPrivilege x = converter.fromString(perm);
-              LOGGER.info("{} GRANT permission {}", getDryRunMessage(), perm);
-              if (!dryRun) {
-                client.grantPrivilege(requestorName, r.getRoleName(), component, x);
-              }
-            }
-
-            // Revoke old permission (only if not part of migrated permissions)
-            if (!originalPermPresent) {
-              LOGGER.info("{} REVOKE permission {}", getDryRunMessage(), privilegeStr);
-              if (!dryRun) {
-                client.revokePrivilege(requestorName, r.getRoleName(), component, p);
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-  private void migratePolicyFile () throws Exception {
-    Configuration conf = getSentryConf();
-    Path sourceFile = new Path (policyFile.get());
-    SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf, sourceFile);
-    ProviderBackendContext ctx = new ProviderBackendContext();
-    policyFileBackend.initialize(ctx);
-
-    Set<String> roles = Sets.newHashSet();
-    Table<String, String, Set<String>> groupRolePrivilegeTable =
-        policyFileBackend.getGroupRolePrivilegeTable();
-
-    Ini output = PolicyFiles.loadFromPath(sourceFile.getFileSystem(conf), sourceFile);
-    Ini.Section rolesSection = output.get(PolicyFileConstants.ROLES);
-
-    for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
-      for (String roleName : policyFileBackend.getRoles(Collections.singleton(groupName), ActiveRoleSet.ALL)) {
-        if (!roles.contains(roleName)) {
-          // Do the actual migration
-          Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
-          Collection<String> migrated = transformPrivileges(privileges);
-
-          if (!migrated.isEmpty()) {
-            LOGGER.info("{} For role {} migrating privileges from {} to {}", getDryRunMessage(),
-                roleName, privileges, migrated);
-            if (!dryRun) {
-              rolesSection.put(roleName, PrivilegeUtils.fromPrivilegeStrings(migrated));
-            }
-          }
-
-          roles.add(roleName);
-        }
-      }
-    }
-
-    if (!dryRun) {
-      Path targetFile = new Path (outputFile.get());
-      PolicyFiles.writeToPath(output, targetFile.getFileSystem(conf), targetFile);
-      LOGGER.info("Successfully saved migrated Sentry policy file at {}", outputFile.get());
-    }
-  }
-
-  private String getDryRunMessage() {
-    return dryRun ? "[Dry Run]" : "";
-  }
-
-  private Configuration getSentryConf() {
-    Configuration conf = new Configuration();
-    if (confPath.isPresent()) {
-      conf.addResource(new Path(confPath.get()), true);
-    }
-    return conf;
-  }
-
-  @VisibleForTesting
-  public boolean executeConfigTool(String [] args) throws Exception {
-    boolean result = true;
-    if (parseArgs(args)) {
-      run();
-    } else {
-      result = false;
-    }
-    return result;
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolSolr.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolSolr.java
deleted file mode 100644
index 5799993..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/PermissionsMigrationToolSolr.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.sentry.core.common.utils.SentryConstants;
-import org.apache.sentry.core.model.solr.validator.SolrPrivilegeValidator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This class provides SOLR specific functionality required for migrating Sentry privileges.
- */
-public class PermissionsMigrationToolSolr extends PermissionsMigrationToolCommon {
-  private static final Logger LOGGER = LoggerFactory.getLogger(PermissionsMigrationToolSolr.class);
-
-
-  @Override
-  protected String getComponent(Configuration conf) {
-    return "SOLR";
-  }
-
-  @Override
-  protected String getServiceName(Configuration conf) {
-    return conf.get(SOLR_SERVICE_NAME, "service1");
-  }
-
-  @Override
-  protected Collection<String> transformPrivileges(Collection<String> privileges) {
-    List<String> result = new ArrayList<>();
-    boolean migrated = false;
-
-    if (getSourceVersion().major == 1) { // Migrate only Sentry 1.x permissions
-      for (String p : privileges) {
-        SolrPrivilegeValidator v = new SolrPrivilegeValidator();
-        v.validate(p, false);
-
-        if ("collection".equalsIgnoreCase(v.getEntityType()) && "admin".equalsIgnoreCase(v.getEntityName())) {
-          result.add(getPermissionStr("admin", "collections", v.getActionName()));
-          result.add(getPermissionStr("admin", "cores", v.getActionName()));
-          migrated = true;
-        } else if ("collection".equalsIgnoreCase(v.getEntityType()) && "*".equals(v.getEntityName())) {
-          result.add(getPermissionStr("admin", "collections", v.getActionName()));
-          result.add(getPermissionStr("admin", "cores", v.getActionName()));
-          result.add(p);
-          migrated = true;
-        } else {
-          result.add(p);
-        }
-      }
-    }
-
-    return migrated ? result : Collections.emptyList();
-  }
-
-  private String getPermissionStr (String entityType, String entityName, String action) {
-    StringBuilder builder = new StringBuilder();
-    builder.append(entityType);
-    builder.append(SentryConstants.KV_SEPARATOR);
-    builder.append(entityName);
-    if (action != null) {
-      builder.append(SentryConstants.AUTHORIZABLE_SEPARATOR);
-      builder.append(SentryConstants.PRIVILEGE_NAME);
-      builder.append(SentryConstants.KV_SEPARATOR);
-      builder.append(action);
-    }
-    return builder.toString();
-  }
-
-  public static void main(String[] args) throws Exception {
-    PermissionsMigrationToolSolr solrTool = new PermissionsMigrationToolSolr();
-    try {
-      solrTool.executeConfigTool(args);
-    } catch (Exception e) {
-      LOGGER.error(e.getMessage(), e);
-      Throwable current = e;
-      // find the first printable message;
-      while (current != null && current.getMessage() == null) {
-        current = current.getCause();
-      }
-      String error = "";
-      if (current != null && current.getMessage() != null) {
-        error = "Message: " + current.getMessage();
-      }
-      System.out.println("The operation failed. " + error);
-      System.exit(1);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolCommon.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolCommon.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolCommon.java
deleted file mode 100644
index 013e824..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolCommon.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.Parser;
-
-abstract public class SentryConfigToolCommon {
-  private String policyFile;
-  private boolean validate;
-  private boolean importPolicy;
-  private boolean checkCompat;
-  private String confPath;
-
- /**
-   *  parse arguments
-   * <pre>
-   *   -conf,--sentry_conf <filepath>     sentry config file path
-   *   -p,--policy_ini     <arg>          policy file path
-   *   -v,--validate                      validate policy file
-   *   -c,--checkcompat                   check compatibility with service
-   *   -i,--import                        import policy file
-   *   -h,--help                          print usage
-   * </pre>
-   * @param args
-   */
-  protected boolean parseArgs(String [] args) {
-    Options options = new Options();
-
-    Option globalPolicyPath = new Option("p", "policy_ini", true,
-        "Policy file path");
-    globalPolicyPath.setRequired(true);
-    options.addOption(globalPolicyPath);
-
-    Option validateOpt = new Option("v", "validate", false,
-        "Validate policy file");
-    validateOpt.setRequired(false);
-    options.addOption(validateOpt);
-
-    Option checkCompatOpt = new Option("c","checkcompat",false,
-        "Check compatibility with Sentry Service");
-    checkCompatOpt.setRequired(false);
-    options.addOption(checkCompatOpt);
-
-    Option importOpt = new Option("i", "import", false,
-        "Import policy file");
-    importOpt.setRequired(false);
-    options.addOption(importOpt);
-
-    // file path of sentry-site
-    Option sentrySitePathOpt = new Option("conf", "sentry_conf", true, "sentry-site file path");
-    sentrySitePathOpt.setRequired(true);
-    options.addOption(sentrySitePathOpt);
-
-    // help option
-    Option helpOpt = new Option("h", "help", false, "Shell usage");
-    helpOpt.setRequired(false);
-    options.addOption(helpOpt);
-
-    // this Options is parsed first for help option
-    Options helpOptions = new Options();
-    helpOptions.addOption(helpOpt);
-
-    try {
-      Parser parser = new GnuParser();
-
-      // parse help option first
-      CommandLine cmd = parser.parse(helpOptions, args, true);
-      for (Option opt : cmd.getOptions()) {
-        if (opt.getOpt().equals("h")) {
-          // get the help option, print the usage and exit
-          usage(options);
-          return false;
-        }
-      }
-
-      // without help option
-      cmd = parser.parse(options, args);
-
-      for (Option opt : cmd.getOptions()) {
-        if (opt.getOpt().equals("p")) {
-          policyFile = opt.getValue();
-        } else if (opt.getOpt().equals("v")) {
-          validate = true;
-        } else if (opt.getOpt().equals("i")) {
-          importPolicy = true;
-        } else if (opt.getOpt().equals("c")) {
-          checkCompat = true;
-        } else if (opt.getOpt().equals("conf")) {
-          confPath = opt.getValue();
-        }
-      }
-
-      if (!validate && !importPolicy) {
-        throw new IllegalArgumentException("No action specified; at least one of action or import must be specified");
-      }
-    } catch (ParseException pe) {
-      System.out.println(pe.getMessage());
-      usage(options);
-      return false;
-    }
-    return true;
-  }
-
-  // print usage
-  private void usage(Options sentryOptions) {
-    HelpFormatter formatter = new HelpFormatter();
-    formatter.printHelp("sentryConfigTool", sentryOptions);
-  }
-
-  public abstract void run() throws Exception;
-
-  @VisibleForTesting
-  public boolean executeConfigTool(String [] args) throws Exception {
-    boolean result = true;
-    if (parseArgs(args)) {
-      run();
-    } else {
-      result = false;
-    }
-    return result;
-  }
-
-  public String getPolicyFile() { return policyFile; }
-  public boolean getValidate() { return validate; }
-  public boolean getImportPolicy() { return importPolicy; }
-  public boolean getCheckCompat() { return checkCompat; }
-  public String getConfPath() { return confPath; }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolIndexer.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolIndexer.java
deleted file mode 100644
index a5996a7..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolIndexer.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.core.common.Action;
-import org.apache.sentry.core.common.exception.SentryConfigurationException;
-import org.apache.sentry.core.common.utils.KeyValue;
-import org.apache.sentry.core.model.indexer.IndexerPrivilegeModel;
-import org.apache.sentry.provider.common.ProviderBackend;
-import org.apache.sentry.provider.common.ProviderBackendContext;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
-import org.apache.sentry.provider.file.SimpleFileProviderBackend;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_SPLITTER;
-import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
-import static org.apache.sentry.service.thrift.ServiceConstants.ClientConfig.SERVICE_NAME;
-
-/**
- * SentryConfigToolIndexer is an administrative tool used to parse a HBase Indexer policy file
- * and add the role, group mappings, and privileges therein to the Sentry service.
- */
-public class SentryConfigToolIndexer {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(SentryConfigToolIndexer.class);
-
-  private String policyFile;
-  private boolean validate;
-  private boolean importPolicy;
-  private boolean checkCompat;
-  private String confPath;
-
-  private String serviceName;
-
-
-
-  public String getPolicyFile() { return policyFile; }
-
-  public boolean getValidate() { return validate; }
-  public boolean getImportPolicy() { return importPolicy; }
-  public boolean getCheckCompat() { return checkCompat; }
-  public String getConfPath() { return confPath; }
-  public String getServiceName() {
-    return serviceName;
-  }
-
-  /**
-   * Adds command line options for the tool to the passed Options object. Used to extend existing options.
-   * @param options
-   */
-  public void setupOptions(Options options) {
-    Option globalPolicyPath = new Option("f", "policy_ini", true,
-            "Policy file path");
-    globalPolicyPath.setRequired(false);
-    options.addOption(globalPolicyPath);
-
-    Option validateOpt = new Option("v", "validate", false,
-            "Validate policy file");
-    validateOpt.setRequired(false);
-    options.addOption(validateOpt);
-
-    Option checkCompatOpt = new Option("c","checkcompat",false,
-            "Check compatibility with Sentry Service");
-    checkCompatOpt.setRequired(false);
-    options.addOption(checkCompatOpt);
-
-    Option importOpt = new Option("i", "import", false,
-            "Import policy file");
-    importOpt.setRequired(false);
-    options.addOption(importOpt);
-
-  }
-
-  /**
-   * Parses and processes the arguments from the given command line object.
-   * @param cmd
-   */
-  public void parseOptions(CommandLine cmd) {
-    boolean isToolActive = false;
-    for (Option opt : cmd.getOptions()) {
-      if (opt.getOpt().equals("mgr")) {
-        isToolActive = true;
-      }
-    }
-    if (!isToolActive) {
-      return;
-    }
-    for (Option opt : cmd.getOptions()) {
-      if (opt.getOpt().equals("f")) {
-        policyFile = opt.getValue();
-      } else if (opt.getOpt().equals("v")) {
-        validate = true;
-      } else if (opt.getOpt().equals("i")) {
-        importPolicy = true;
-      } else if (opt.getOpt().equals("c")) {
-        checkCompat = true;
-      } else if (opt.getOpt().equals("conf")) {
-        confPath = opt.getValue();
-      } else if (opt.getOpt().equals("s")) {
-        serviceName = opt.getValue();
-      }
-    }
-    if (policyFile == null) {
-      throw new IllegalArgumentException("Missing required option: f");
-    }
-    if (!validate && !importPolicy) {
-      throw new IllegalArgumentException("No action specified; at least one of action or import must be specified");
-    }
-  }
-
-
-  /**
-   * Processes the necessary command based on the arguments parsed earlier.
-   * @throws Exception
-   */
-  public void run() throws Exception {
-    String component = HBASE_INDEXER;
-    Configuration conf = getSentryConf();
-
-    String service = conf.get(SERVICE_NAME, getServiceName());
-
-    if (service == null) {
-      throw new IllegalArgumentException("Service was not defined. Please, use -s command option, or sentry.provider.backend.generic.service-name configuration entry.");
-    }
-
-    LOGGER.info(String.format("Context: component=%s, service=%s", component, service));
-    // instantiate a solr client for sentry service.  This sets the ugi, so must
-    // be done before getting the ugi below.
-    try(SentryGenericServiceClient client =
-                SentryGenericServiceClientFactory.create(conf)) {
-      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
-      String requestorName = ugi.getShortUserName();
-
-      convertINIToSentryServiceCmds(component, service, requestorName, conf, client,
-              getPolicyFile(), getValidate(), getImportPolicy(), getCheckCompat());
-    }
-  }
-
-  private Configuration getSentryConf() {
-    Configuration conf = new Configuration();
-    conf.addResource(new Path(getConfPath()), true);
-    return conf;
-  }
-
-  private void convertINIToSentryServiceCmds(String component,
-      String service, String requestorName,
-      Configuration conf, SentryGenericServiceClient client,
-      String policyFile, boolean validate, boolean importPolicy,
-      boolean checkCompat) throws Exception {
-
-    //instantiate a file providerBackend for parsing
-    LOGGER.info("Reading policy file at: " + policyFile);
-    SimpleFileProviderBackend policyFileBackend =
-        new SimpleFileProviderBackend(conf, policyFile);
-    ProviderBackendContext context = new ProviderBackendContext();
-    context.setValidators(IndexerPrivilegeModel.getInstance().getPrivilegeValidators());
-    policyFileBackend.initialize(context);
-    if (validate) {
-      validatePolicy(policyFileBackend);
-    }
-
-    if (checkCompat) {
-      checkCompat(policyFileBackend);
-    }
-
-    //import the relations about group,role and privilege into the DB store
-    Set<String> roles = Sets.newHashSet();
-    Table<String, String, Set<String>> groupRolePrivilegeTable =
-        policyFileBackend.getGroupRolePrivilegeTable();
-    GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, service, false);
-
-    for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
-      for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
-        if (!roles.contains(roleName)) {
-          LOGGER.info(dryRunMessage(importPolicy) + "Creating role: " + roleName.toLowerCase(Locale.US));
-          if (importPolicy) {
-            client.createRoleIfNotExist(requestorName, roleName, component);
-          }
-          roles.add(roleName);
-        }
-
-        Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
-        if (privileges == null) {
-          continue;
-        }
-        LOGGER.info(dryRunMessage(importPolicy) + "Adding role: " + roleName.toLowerCase(Locale.US) + " to group: " + groupName);
-        if (importPolicy) {
-          client.grantRoleToGroups(requestorName, roleName, component, Sets.newHashSet(groupName));
-        }
-
-        for (String permission : privileges) {
-          String action = null;
-
-          for (String authorizable : AUTHORIZABLE_SPLITTER.
-              trimResults().split(permission)) {
-            KeyValue kv = new KeyValue(authorizable);
-            String key = kv.getKey();
-            String value = kv.getValue();
-            if ("action".equalsIgnoreCase(key)) {
-              action = value;
-            }
-          }
-
-          // Service doesn't support not specifying action
-          if (action == null) {
-            permission += "->action=" + Action.ALL;
-          }
-          LOGGER.info(dryRunMessage(importPolicy) + "Adding permission: " + permission + " to role: " + roleName.toLowerCase(Locale.US));
-          if (importPolicy) {
-            client.grantPrivilege(requestorName, roleName, component, converter.fromString(permission));
-          }
-        }
-      }
-    }
-  }
-
-  private void validatePolicy(ProviderBackend backend) throws Exception {
-    try {
-      backend.validatePolicy(true);
-    } catch (SentryConfigurationException e) {
-      printConfigErrorsWarnings(e);
-      throw e;
-    }
-  }
-
-  private void printConfigErrorsWarnings(SentryConfigurationException configException) {
-    System.out.println(" *** Found configuration problems *** ");
-    for (String errMsg : configException.getConfigErrors()) {
-      System.out.println("ERROR: " + errMsg);
-    }
-    for (String warnMsg : configException.getConfigWarnings()) {
-      System.out.println("Warning: " + warnMsg);
-    }
-  }
-
-  private void checkCompat(SimpleFileProviderBackend backend) throws Exception {
-    Map<String, Set<String>> rolesCaseMapping = new HashMap<String, Set<String>>();
-    Table<String, String, Set<String>> groupRolePrivilegeTable =
-      backend.getGroupRolePrivilegeTable();
-
-    for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
-      String roleNameLower = roleName.toLowerCase(Locale.US);
-      if (!roleName.equals(roleNameLower)) {
-        if (!rolesCaseMapping.containsKey(roleNameLower)) {
-          rolesCaseMapping.put(roleNameLower, Sets.newHashSet(roleName));
-        } else {
-          rolesCaseMapping.get(roleNameLower).add(roleName);
-        }
-      }
-    }
-
-    List<String> errors = new LinkedList<String>();
-    StringBuilder warningString = new StringBuilder();
-    if (!rolesCaseMapping.isEmpty()) {
-      warningString.append("The following roles names will be lower cased when added to the Sentry Service.\n");
-      warningString.append("This will cause document-level security to fail to match the role tokens.\n");
-      warningString.append("Role names: ");
-    }
-    boolean firstWarning = true;
-
-    for (Map.Entry<String, Set<String>> entry : rolesCaseMapping.entrySet()) {
-      Set<String> caseMapping = entry.getValue();
-      if (caseMapping.size() > 1) {
-        StringBuilder errorString = new StringBuilder();
-        errorString.append("The following (cased) roles map to the same role in the sentry service: ");
-        boolean first = true;
-        for (String casedRole : caseMapping) {
-          errorString.append(first ? "" : ", ");
-          errorString.append(casedRole);
-          first = false;
-        }
-        errorString.append(".  Role in service: ").append(entry.getKey());
-        errors.add(errorString.toString());
-      }
-
-      for (String casedRole : caseMapping) {
-        warningString.append(firstWarning? "" : ", ");
-        warningString.append(casedRole);
-        firstWarning = false;
-      }
-    }
-
-    for (String error : errors) {
-      System.out.println("ERROR: " + error);
-    }
-    System.out.println("\n");
-
-    System.out.println("Warning: " + warningString.toString());
-    if (errors.size() > 0) {
-      SentryConfigurationException ex =
-          new SentryConfigurationException("Compatibility check failure");
-      ex.setConfigErrors(errors);
-      ex.setConfigWarnings(Lists.<String>asList(warningString.toString(), new String[0]));
-      throw ex;
-    }
-  }
-
-  private String dryRunMessage(boolean importPolicy) {
-    if (importPolicy) {
-      return "";
-    } else {
-      return "[Dry Run] ";
-    }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolSolr.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolSolr.java
deleted file mode 100644
index 1a4692e..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryConfigToolSolr.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.core.common.Action;
-import org.apache.sentry.core.common.exception.SentryConfigurationException;
-import org.apache.sentry.core.common.utils.KeyValue;
-import org.apache.sentry.core.common.utils.SentryConstants;
-import org.apache.sentry.core.model.solr.SolrPrivilegeModel;
-import org.apache.sentry.provider.common.ProviderBackend;
-import org.apache.sentry.provider.common.ProviderBackendContext;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
-import org.apache.sentry.provider.file.SimpleFileProviderBackend;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * SentryConfigToolSolr is an administrative tool used to parse a Solr policy file
- * and add the role, group mappings, and privileges therein to the Sentry service.
- */
-public class SentryConfigToolSolr extends SentryConfigToolCommon {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(SentryConfigToolSolr.class);
-  public static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
-
-  @Override
-  public void run() throws Exception {
-    String component = "SOLR";
-    Configuration conf = getSentryConf();
-
-    String service = conf.get(SOLR_SERVICE_NAME, "service1");
-    // instantiate a solr client for sentry service.  This sets the ugi, so must
-    // be done before getting the ugi below.
-    try(SentryGenericServiceClient client =
-                SentryGenericServiceClientFactory.create(conf)) {
-      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
-      String requestorName = ugi.getShortUserName();
-
-      convertINIToSentryServiceCmds(component, service, requestorName, conf, client,
-              getPolicyFile(), getValidate(), getImportPolicy(), getCheckCompat());
-    }
-  }
-
-  private Configuration getSentryConf() {
-    Configuration conf = new Configuration();
-    conf.addResource(new Path(getConfPath()), true);
-    return conf;
-  }
-
-   /**
-    * Convert policy file to solrctl commands -- based on SENTRY-480
-    */
-  private void convertINIToSentryServiceCmds(String component,
-      String service, String requestorName,
-      Configuration conf, SentryGenericServiceClient client,
-      String policyFile, boolean validate, boolean importPolicy,
-      boolean checkCompat) throws Exception {
-
-    //instantiate a file providerBackend for parsing
-    LOGGER.info("Reading policy file at: " + policyFile);
-    SimpleFileProviderBackend policyFileBackend =
-        new SimpleFileProviderBackend(conf, policyFile);
-    ProviderBackendContext context = new ProviderBackendContext();
-    context.setValidators(SolrPrivilegeModel.getInstance().getPrivilegeValidators());
-    policyFileBackend.initialize(context);
-    if (validate) {
-      validatePolicy(policyFileBackend);
-    }
-
-    if (checkCompat) {
-      checkCompat(policyFileBackend);
-    }
-
-    //import the relations about group,role and privilege into the DB store
-    Set<String> roles = Sets.newHashSet();
-    Table<String, String, Set<String>> groupRolePrivilegeTable =
-        policyFileBackend.getGroupRolePrivilegeTable();
-    GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, service, false);
-
-    for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
-      for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
-        if (!roles.contains(roleName)) {
-          LOGGER.info(dryRunMessage(importPolicy) + "Creating role: " + roleName.toLowerCase(Locale.US));
-          if (importPolicy) {
-            client.createRoleIfNotExist(requestorName, roleName, component);
-          }
-          roles.add(roleName);
-        }
-
-        Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
-        if (privileges == null) {
-          continue;
-        }
-        LOGGER.info(dryRunMessage(importPolicy) + "Adding role: " + roleName.toLowerCase(Locale.US) + " to group: " + groupName);
-        if (importPolicy) {
-          client.grantRoleToGroups(requestorName, roleName, component, Sets.newHashSet(groupName));
-        }
-
-        for (String permission : privileges) {
-          String action = null;
-
-          for (String authorizable : SentryConstants.AUTHORIZABLE_SPLITTER.
-              trimResults().split(permission)) {
-            KeyValue kv = new KeyValue(authorizable);
-            String key = kv.getKey();
-            String value = kv.getValue();
-            if ("action".equalsIgnoreCase(key)) {
-              action = value;
-            }
-          }
-
-          // Service doesn't support not specifying action
-          if (action == null) {
-            permission += "->action=" + Action.ALL;
-          }
-          LOGGER.info(dryRunMessage(importPolicy) + "Adding permission: " + permission + " to role: " + roleName.toLowerCase(Locale.US));
-          if (importPolicy) {
-            client.grantPrivilege(requestorName, roleName, component, converter.fromString(permission));
-          }
-        }
-      }
-    }
-  }
-
-  private void validatePolicy(ProviderBackend backend) throws Exception {
-    try {
-      backend.validatePolicy(true);
-    } catch (SentryConfigurationException e) {
-      printConfigErrorsWarnings(e);
-      throw e;
-    }
-  }
-
-  private void printConfigErrorsWarnings(SentryConfigurationException configException) {
-    System.out.println(" *** Found configuration problems *** ");
-    for (String errMsg : configException.getConfigErrors()) {
-      System.out.println("ERROR: " + errMsg);
-    }
-    for (String warnMsg : configException.getConfigWarnings()) {
-      System.out.println("Warning: " + warnMsg);
-    }
-  }
-
-  private void checkCompat(SimpleFileProviderBackend backend) throws Exception {
-    Map<String, Set<String>> rolesCaseMapping = new HashMap<String, Set<String>>();
-    Table<String, String, Set<String>> groupRolePrivilegeTable =
-      backend.getGroupRolePrivilegeTable();
-
-    for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
-      String roleNameLower = roleName.toLowerCase(Locale.US);
-      if (!roleName.equals(roleNameLower)) {
-        if (!rolesCaseMapping.containsKey(roleNameLower)) {
-          rolesCaseMapping.put(roleNameLower, Sets.newHashSet(roleName));
-        } else {
-          rolesCaseMapping.get(roleNameLower).add(roleName);
-        }
-      }
-    }
-
-    List<String> errors = new LinkedList<String>();
-    StringBuilder warningString = new StringBuilder();
-    if (!rolesCaseMapping.isEmpty()) {
-      warningString.append("The following roles names will be lower cased when added to the Sentry Service.\n");
-      warningString.append("This will cause document-level security to fail to match the role tokens.\n");
-      warningString.append("Role names: ");
-    }
-    boolean firstWarning = true;
-
-    for (Map.Entry<String, Set<String>> entry : rolesCaseMapping.entrySet()) {
-      Set<String> caseMapping = entry.getValue();
-      if (caseMapping.size() > 1) {
-        StringBuilder errorString = new StringBuilder();
-        errorString.append("The following (cased) roles map to the same role in the sentry service: ");
-        boolean first = true;
-        for (String casedRole : caseMapping) {
-          errorString.append(first ? "" : ", ");
-          errorString.append(casedRole);
-          first = false;
-        }
-        errorString.append(".  Role in service: ").append(entry.getKey());
-        errors.add(errorString.toString());
-      }
-
-      for (String casedRole : caseMapping) {
-        warningString.append(firstWarning? "" : ", ");
-        warningString.append(casedRole);
-        firstWarning = false;
-      }
-    }
-
-    for (String error : errors) {
-      System.out.println("ERROR: " + error);
-    }
-    System.out.println("\n");
-
-    System.out.println("Warning: " + warningString.toString());
-    if (errors.size() > 0) {
-      SentryConfigurationException ex =
-          new SentryConfigurationException("Compatibility check failure");
-      ex.setConfigErrors(errors);
-      ex.setConfigWarnings(Lists.<String>asList(warningString.toString(), new String[0]));
-      throw ex;
-    }
-  }
-
-  private String dryRunMessage(boolean importPolicy) {
-    if (importPolicy) {
-      return "";
-    } else {
-      return "[Dry Run] ";
-    }
-  }
-
-  public static void main(String[] args) throws Exception {
-    SentryConfigToolSolr solrTool = new SentryConfigToolSolr();
-    try {
-      solrTool.executeConfigTool(args);
-    } catch (Exception e) {
-      LOGGER.error(e.getMessage(), e);
-      Throwable current = e;
-      // find the first printable message;
-      while (current != null && current.getMessage() == null) {
-        current = current.getCause();
-      }
-      String error = "";
-      if (current != null && current.getMessage() != null) {
-        error = "Message: " + current.getMessage();
-      }
-      System.out.println("The operation failed. " + error);
-      System.exit(1);
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellGeneric.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellGeneric.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellGeneric.java
deleted file mode 100644
index 4487685..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellGeneric.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import com.google.common.collect.Sets;
-import org.apache.commons.lang.StringUtils;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.provider.common.AuthorizationComponent;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
-import org.apache.sentry.provider.db.generic.tools.command.GenericShellCommand;
-import org.apache.sentry.provider.db.generic.tools.command.TSentryPrivilegeConverter;
-import org.apache.sentry.provider.db.tools.SentryShellCommon;
-import org.apache.sentry.provider.db.tools.ShellCommand;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * SentryShellGeneric is an admin tool, and responsible for the management of repository.
- * The following commands are supported:
- * create role, drop role, add group to role, grant privilege to role,
- * revoke privilege from role, list roles, list privilege for role.
- */
-public class SentryShellGeneric extends SentryShellCommon {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellGeneric.class);
-  private static final String KAFKA_SERVICE_NAME = "sentry.service.client.kafka.service.name";
-  private static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
-  private static final String SQOOP_SERVICE_NAME = "sentry.service.client.sqoop.service.name";
-
-  @Override
-  public void run() throws Exception {
-    String component = getComponent();
-    Configuration conf = getSentryConf();
-
-    String service = getService(conf);
-    try (SentryGenericServiceClient client =
-                SentryGenericServiceClientFactory.create(conf)) {
-      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
-      String requestorName = ugi.getShortUserName();
-      TSentryPrivilegeConverter converter = getPrivilegeConverter(component, service);
-      ShellCommand command = new GenericShellCommand(client, component, service, converter);
-
-      // check the requestor name
-      if (StringUtils.isEmpty(requestorName)) {
-        // The exception message will be recorded in log file.
-        throw new Exception("The requestor name is empty.");
-      }
-
-      if (isCreateRole) {
-        command.createRole(requestorName, roleName);
-      } else if (isDropRole) {
-        command.dropRole(requestorName, roleName);
-      } else if (isAddRoleGroup) {
-        Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
-        command.grantRoleToGroups(requestorName, roleName, groups);
-      } else if (isDeleteRoleGroup) {
-        Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
-        command.revokeRoleFromGroups(requestorName, roleName, groups);
-      } else if (isGrantPrivilegeRole) {
-        command.grantPrivilegeToRole(requestorName, roleName, privilegeStr);
-      } else if (isRevokePrivilegeRole) {
-        command.revokePrivilegeFromRole(requestorName, roleName, privilegeStr);
-      } else if (isListRole) {
-        List<String> roles = command.listRoles(requestorName, groupName);
-        for (String role : roles) {
-          System.out.println(role);
-        }
-      } else if (isListPrivilege) {
-        List<String> privileges = command.listPrivileges(requestorName, roleName);
-        for (String privilege : privileges) {
-          System.out.println(privilege);
-        }
-      } else if (isListGroup) {
-        List<String> groups = command.listGroupRoles(requestorName);
-        for (String group : groups) {
-          System.out.println(group);
-        }
-      }
-    }
-  }
-
-  protected GenericPrivilegeConverter getPrivilegeConverter(String component, String service) {
-    return new GenericPrivilegeConverter(component, service);
-  }
-
-  protected String getComponent() throws Exception {
-    if (type == TYPE.kafka) {
-      return AuthorizationComponent.KAFKA;
-    } else if (type == TYPE.solr) {
-      return "SOLR";
-    } else if (type == TYPE.sqoop) {
-      return AuthorizationComponent.SQOOP;
-    }
-
-    throw new Exception("Invalid type specified for SentryShellGeneric: " + type);
-  }
-
-  protected String getService(Configuration conf) throws Exception {
-    if (type == TYPE.kafka) {
-      return conf.get(KAFKA_SERVICE_NAME, AuthorizationComponent.KAFKA);
-    } else if (type == TYPE.solr) {
-      return conf.get(SOLR_SERVICE_NAME, "service1");
-    } else if (type == TYPE.sqoop) {
-      return conf.get(SQOOP_SERVICE_NAME, "sqoopServer1");
-    }
-
-    throw new Exception("Invalid type specified for SentryShellGeneric: " + type);
-  }
-
-  private Configuration getSentryConf() {
-    Configuration conf = new Configuration();
-    conf.addResource(new Path(confPath), true);
-    return conf;
-  }
-
-  public static void main(String[] args) throws Exception {
-    SentryShellGeneric sentryShell = new SentryShellGeneric();
-    try {
-      sentryShell.executeShell(args);
-    } catch (Exception e) {
-      LOGGER.error(e.getMessage(), e);
-      Throwable current = e;
-      // find the first printable message;
-      while (current != null && current.getMessage() == null) {
-        current = current.getCause();
-      }
-      String error = "";
-      if (current != null && current.getMessage() != null) {
-        error = "Message: " + current.getMessage();
-      }
-      System.out.println("The operation failed. " + error);
-      System.exit(1);
-    }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellIndexer.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellIndexer.java
deleted file mode 100644
index 5bbe772..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/SentryShellIndexer.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * 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
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * 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.sentry.provider.db.generic.tools;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionGroup;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.hadoop.conf.Configuration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
-import static org.apache.sentry.service.thrift.ServiceConstants.ClientConfig.SERVICE_NAME;
-
-/**
- * SentryShellIndexer is an admin tool, and responsible for the management of repository.
- * The following commands are supported:
- * create role, drop role, add group to role, grant privilege to role,
- * revoke privilege from role, list roles, list privilege for role.
- */
-public class SentryShellIndexer extends SentryShellGeneric {
-
-  protected boolean isMigration = false;
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellIndexer.class);
-
-  private final SentryConfigToolIndexer configTool = new SentryConfigToolIndexer();
-
-  @Override
-  protected void setupOptions(Options simpleShellOptions) {
-    super.setupOptions(simpleShellOptions);
-    configTool.setupOptions(simpleShellOptions);
-  }
-
-  @Override
-  protected void parseOptions(CommandLine cmd) throws ParseException {
-    super.parseOptions(cmd);
-    configTool.parseOptions(cmd);
-    for (Option opt : cmd.getOptions()) {
-      if (opt.getOpt().equals("mgr")) {
-        isMigration = true;
-      }
-    }
-  }
-
-  @Override
-  protected OptionGroup getMainOptions() {
-    OptionGroup mainOptions = super.getMainOptions();
-    Option mgrOpt = new Option("mgr", "migrate", false, "Migrate ini file to Sentry service");
-    mgrOpt.setRequired(false);
-    mainOptions.addOption(mgrOpt);
-    return mainOptions;
-  }
-
-  /**
-   * Processes the necessary command based on the arguments parsed earlier.
-   * @throws Exception
-   */
-  @Override
-  public void run() throws Exception {
-
-    if (isMigration) {
-      configTool.run();
-      return;
-    }
-
-    super.run();
-  }
-
-  @Override
-  protected String getComponent() throws Exception {
-    return HBASE_INDEXER;
-  }
-
-  @Override
-  protected String getService(Configuration conf) throws Exception {
-    String service = conf.get(SERVICE_NAME, serviceName);
-    if (service == null) {
-      throw new IllegalArgumentException("Service was not defined. Please, use -s command option, or sentry.provider.backend.generic.service-name configuration entry.");
-    }
-    return service;
-  }
-
-  /**
-   * Entry-point for Hbase indexer cli tool.
-   * @param args
-   * @throws Exception
-   */
-  public static void main(String[] args) throws Exception {
-    SentryShellIndexer sentryShell = new SentryShellIndexer();
-    try {
-      sentryShell.executeShell(args);
-    } catch (Exception e) {
-      LOGGER.error(e.getMessage(), e);
-      Throwable current = e;
-      // find the first printable message;
-      while (current != null && current.getMessage() == null) {
-        current = current.getCause();
-      }
-      System.out.println("The operation failed." +
-              (current.getMessage() == null ? "" : "  Message: " + current.getMessage()));
-      System.exit(1);
-    }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/TSentryPrivilegeConverter.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/TSentryPrivilegeConverter.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/TSentryPrivilegeConverter.java
new file mode 100644
index 0000000..5e48483
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/TSentryPrivilegeConverter.java
@@ -0,0 +1,35 @@
+/*
+ *
+ * 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.sentry.provider.db.generic.tools;
+
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+
+public interface TSentryPrivilegeConverter {
+
+  /**
+   * Convert string to privilege
+   */
+  TSentryPrivilege fromString(String privilegeStr) throws SentryUserException;
+
+  /**
+   * Convert privilege to string
+   */
+  String toString(TSentryPrivilege tSentryPrivilege);
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/GenericShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/GenericShellCommand.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/GenericShellCommand.java
deleted file mode 100644
index a792b5c..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/GenericShellCommand.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools.command;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.tools.ShellCommand;
-
-/**
- * The ShellCommand implementation for the Generic clients
- */
-public class GenericShellCommand implements ShellCommand {
-
-  private final SentryGenericServiceClient client;
-  private final String component;
-  private final TSentryPrivilegeConverter converter;
-  private final String serviceName;
-
-  public GenericShellCommand(SentryGenericServiceClient client, String component, String serviceName,
-                             TSentryPrivilegeConverter converter) {
-    this.client = client;
-    this.component = component;
-    this.serviceName = serviceName;
-    this.converter = converter;
-  }
-
-  public void createRole(String requestorName, String roleName) throws SentryUserException {
-    client.createRole(requestorName, roleName, component);
-  }
-
-  public void dropRole(String requestorName, String roleName) throws SentryUserException {
-    client.dropRole(requestorName, roleName, component);
-  }
-
-  public void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException {
-    TSentryPrivilege sentryPrivilege = converter.fromString(privilege);
-    client.grantPrivilege(requestorName, roleName, component, sentryPrivilege);
-  }
-
-  public void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
-    client.grantRoleToGroups(requestorName, roleName, component, groups);
-  }
-
-  public void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException {
-    TSentryPrivilege sentryPrivilege = converter.fromString(privilege);
-    client.revokePrivilege(requestorName, roleName, component, sentryPrivilege);
-  }
-
-  public void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
-    client.revokeRoleFromGroups(requestorName, roleName, component, groups);
-  }
-
-  public List<String> listRoles(String requestorName, String group) throws SentryUserException {
-    Set<TSentryRole> roles;
-    if (StringUtils.isEmpty(group)) {
-      roles = client.listAllRoles(requestorName, component);
-    } else {
-      roles = client.listRolesByGroupName(requestorName, group, component);
-    }
-
-    List<String> result = new ArrayList<>();
-    if (roles != null) {
-      for (TSentryRole role : roles) {
-        result.add(role.getRoleName());
-      }
-    }
-
-    return result;
-  }
-
-  public List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException {
-    Set<TSentryPrivilege> privileges = client
-        .listAllPrivilegesByRoleName(requestorName, roleName, component, serviceName);
-
-    List<String> result = new ArrayList<>();
-    if (privileges != null) {
-      for (TSentryPrivilege privilege : privileges) {
-        String privilegeStr = converter.toString(privilege);
-        result.add(privilegeStr);
-      }
-    }
-
-    return result;
-  }
-
-  public List<String> listGroupRoles(String requestorName) throws SentryUserException {
-    Set<TSentryRole> roles = client.listAllRoles(requestorName, component);
-    if (roles == null || roles.isEmpty()) {
-      return Collections.emptyList();
-    }
-
-    // Set of all group names
-    Set<String> groupNames = new HashSet<>();
-
-    // Map group to set of roles
-    Map<String, Set<String>> groupInfo = new HashMap<>();
-
-    // Get all group names
-    for (TSentryRole role: roles) {
-      for (String group : role.getGroups()) {
-        groupNames.add(group);
-        Set<String> groupRoles = groupInfo.get(group);
-        if (groupRoles != null) {
-          // Add a new or existing role
-          groupRoles.add(role.getRoleName());
-          continue;
-        }
-        // Never seen this group before
-        groupRoles = new HashSet<>();
-        groupRoles.add(role.getRoleName());
-        groupInfo.put(group, groupRoles);
-      }
-    }
-
-    List<String> groups = new ArrayList<>(groupNames);
-
-    // Produce printable result as
-    // group1 = role1, role2, ...
-    // group2 = ...
-    List<String> result = new LinkedList<>();
-    for (String groupName: groups) {
-      result.add(groupName + " = " + StringUtils.join(groupInfo.get(groupName), ", "));
-    }
-
-    return result;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java
deleted file mode 100644
index 0bfbc44..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/tools/command/TSentryPrivilegeConverter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools.command;
-
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-
-public interface TSentryPrivilegeConverter {
-
-  /**
-   * Convert string to privilege
-   */
-  TSentryPrivilege fromString(String privilegeStr) throws SentryUserException;
-
-  /**
-   * Convert privilege to string
-   */
-  String toString(TSentryPrivilege tSentryPrivilege);
-}


[7/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.

Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolIndexer.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolIndexer.java
deleted file mode 100644
index 4dddf78..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolIndexer.java
+++ /dev/null
@@ -1,263 +0,0 @@
- /**
- * 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.sentry.provider.db.generic.tools;
-
- import com.google.common.collect.Sets;
- import com.google.common.io.Files;
- import org.apache.commons.io.FileUtils;
- import org.apache.sentry.core.common.exception.SentryConfigurationException;
- import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
- import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
- import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
- import org.apache.sentry.service.thrift.ServiceConstants;
- import org.junit.After;
- import org.junit.Before;
- import org.junit.Test;
-
- import java.io.File;
- import java.io.FileOutputStream;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Map;
- import java.util.Set;
-
- import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
- import static org.junit.Assert.assertEquals;
- import static org.junit.Assert.assertTrue;
- import static org.junit.Assert.fail;
-
- public class TestSentryConfigToolIndexer extends SentryGenericServiceIntegrationBase {
-   private static String RESOURCES_DIR = "target" + File.separator + "test-classes" + File.separator;
-   private static String VALID_POLICY_INI = RESOURCES_DIR + "indexer_config_import_tool.ini";
-   private static String INVALID_POLICY_INI = RESOURCES_DIR + "indexer_invalid.ini";
-   private static String CASE_POLICY_INI = RESOURCES_DIR + "indexer_case.ini";
-   private File confDir;
-   private File confPath;
-   private String requestorName = "";
-   private String service = "service1";
-
-   @Before
-   public void prepareForTest() throws Exception {
-     confDir = Files.createTempDir();
-     confPath = new File(confDir, "sentry-site.xml");
-     conf.set(ServiceConstants.ClientConfig.SERVICE_NAME, service);
-     if (confPath.createNewFile()) {
-       FileOutputStream to = new FileOutputStream(confPath);
-       conf.writeXml(to);
-       to.close();
-     }
-     requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
-     Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
-     setLocalGroupMapping(requestorName, requestorUserGroupNames);
-     // add ADMIN_USER for the after() in SentryServiceIntegrationBase
-     setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
-     writePolicyFile();
-   }
-
-   @After
-   public void clearTestData() throws Exception {
-     FileUtils.deleteQuietly(confDir);
-
-     // clear roles and privileges
-     Set<TSentryRole> tRoles = client.listAllRoles(requestorName, HBASE_INDEXER);
-     for (TSentryRole tRole : tRoles) {
-       String role = tRole.getRoleName();
-       Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
-           requestorName, role, HBASE_INDEXER, service);
-       for (TSentryPrivilege privilege : privileges) {
-         client.revokePrivilege(requestorName, role, HBASE_INDEXER, privilege);
-       }
-       client.dropRole(requestorName, role, HBASE_INDEXER);
-     }
-   }
-
-   @Test
-   public void testConvertIni() throws Exception {
-     runTestAsSubject(new TestOperation() {
-       @Override
-       public void runTestAsSubject() throws Exception {
-         String[] args = {"-mgr", "-f", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
-         SentryShellIndexer sentryTool = new SentryShellIndexer();
-         sentryTool.executeShell(args);
-
-         Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
-         groupMapping.put("corporal_role", Sets.newHashSet("corporal", "sergeant", "general", "commander_in_chief"));
-         groupMapping.put("sergeant_role", Sets.newHashSet("sergeant", "general", "commander_in_chief"));
-         groupMapping.put("general_role", Sets.newHashSet("general", "commander_in_chief"));
-         groupMapping.put("commander_in_chief_role", Sets.newHashSet("commander_in_chief"));
-
-
-         Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
-         privilegeMapping.put("corporal_role",
-             Sets.newHashSet("Indexer=info->action=read", "Indexer=info->action=write"));
-         privilegeMapping.put("sergeant_role",
-             Sets.newHashSet("Indexer=info->action=write"));
-         privilegeMapping.put("general_role",
-             Sets.newHashSet("Indexer=info->action=*"));
-         privilegeMapping.put("commander_in_chief_role",
-             Sets.newHashSet("Indexer=*->action=*"));
-
-         // check roles
-         Set<TSentryRole> tRoles = client.listAllRoles(requestorName, HBASE_INDEXER);
-         assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
-         Set<String> roles = new HashSet<String>();
-         for (TSentryRole tRole : tRoles) {
-           roles.add(tRole.getRoleName());
-         }
-
-         for (String expectedRole : groupMapping.keySet()) {
-           assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
-         }
-
-         // check groups
-         for (TSentryRole tRole : tRoles) {
-           Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
-           assertEquals("Group size doesn't match for role: " + tRole.getRoleName(),
-               expectedGroups.size(), tRole.getGroups().size());
-           assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
-               tRole.getGroups().containsAll(expectedGroups));
-         }
-
-         // check privileges
-         GenericPrivilegeConverter convert = new GenericPrivilegeConverter(HBASE_INDEXER, service);
-         for (String role : roles) {
-           Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
-               requestorName, role, HBASE_INDEXER, service);
-           Set<String> expectedPrivileges = privilegeMapping.get(role);
-           assertEquals("Privilege set size doesn't match for role: " + role,
-               expectedPrivileges.size(), privileges.size());
-
-           Set<String> privilegeStrs = new HashSet<String>();
-           for (TSentryPrivilege privilege : privileges) {
-             privilegeStrs.add(convert.toString(privilege));
-           }
-
-           for (String expectedPrivilege : expectedPrivileges) {
-             assertTrue("Did not find expected privilege: " + expectedPrivilege,
-                 privilegeStrs.contains(expectedPrivilege));
-           }
-         }
-       }
-     });
-   }
-
-   @Test
-   public void testNoPolicyFile() throws Exception {
-     runTestAsSubject(new TestOperation() {
-       @Override
-       public void runTestAsSubject() throws Exception {
-         String[] args = { "-mgr", "-f", INVALID_POLICY_INI + "Foobar", "-conf", confPath.getAbsolutePath(), "-v", "-i"};
-         SentryShellIndexer sentryTool = new SentryShellIndexer();
-         try {
-           sentryTool.executeShell(args);
-           fail("Exception should be thrown for nonexistant ini");
-         } catch (SentryConfigurationException e) {
-           // expected exception
-         }
-       }
-     });
-   }
-
-   @Test
-   public void testNoValidateNorImport() throws Exception {
-     runTestAsSubject(new TestOperation() {
-       @Override
-       public void runTestAsSubject() throws Exception {
-         String[] args = { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath()};
-         SentryShellIndexer sentryTool = new SentryShellIndexer();
-         try {
-           sentryTool.executeShell(args);
-           fail("Exception should be thrown for validating invalid ini");
-         } catch (IllegalArgumentException e) {
-           // expected exception
-         }
-       }
-     });
-   }
-
-   @Test
-   public void testConvertInvalidIni() throws Exception {
-     runTestAsSubject(new TestOperation() {
-       @Override
-       public void runTestAsSubject() throws Exception {
-         // test: validate an invalid ini
-         String[] args = { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
-         SentryShellIndexer sentryTool = new SentryShellIndexer();
-         try {
-           sentryTool.executeShell(args);
-           fail("Exception should be thrown for validating invalid ini");
-         } catch (SentryConfigurationException e) {
-           // expected exception
-         }
-
-         // test without validating, should not error
-         args = new String[] { "-mgr", "-f", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i"};
-         sentryTool = new SentryShellIndexer();
-         sentryTool.executeShell(args);
-       }
-     });
-   }
-
-   @Test
-   public void testCompatCheck() throws Exception {
-     runTestAsSubject(new TestOperation() {
-       @Override
-       public void runTestAsSubject() throws Exception {
-         // test: validate an invalid ini
-         String[] args = { "-mgr", "-f", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
-         SentryShellIndexer sentryTool = new SentryShellIndexer();
-         try {
-           sentryTool.executeShell(args);
-           fail("Exception should be thrown for validating invalid ini");
-         } catch (SentryConfigurationException e) {
-           assertEquals("Expected error", 1, e.getConfigErrors().size());
-           String error = e.getConfigErrors().get(0);
-           assertCasedRoleNamesInMessage(error, "RoLe1", "rOlE1");
-           String warning = e.getConfigWarnings().get(0);
-           assertCasedRoleNamesInMessage(warning, "ROLE2", "RoLe1", "rOlE1");
-           assertEquals("Expected warning", 1, e.getConfigWarnings().size());
-         }
-
-         // test without compat checking
-         args = new String[] { "-mgr", "-f", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i", "-v"};
-         sentryTool = new SentryShellIndexer();
-         sentryTool.executeShell(args);
-       }
-     });
-   }
-
-   // Test that a valid compat check doesn't throw an exception
-   @Test
-   public void testCompatCheckValid() throws Exception {
-     runTestAsSubject(new TestOperation() {
-       @Override
-       public void runTestAsSubject() throws Exception {
-         String[] args = { "-mgr", "-f", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
-         SentryShellIndexer sentryTool = new SentryShellIndexer();
-         sentryTool.executeShell(args);
-       }
-     });
-   }
-
-   private void assertCasedRoleNamesInMessage(String message, String ... casedRoleNames) {
-     for (String casedRoleName : casedRoleNames) {
-       assertTrue("Expected cased role name: " + casedRoleName, message.contains(casedRoleName));
-     }
-   }
- }

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java
deleted file mode 100644
index 9e6ff42..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryConfigToolSolr.java
+++ /dev/null
@@ -1,261 +0,0 @@
- /**
- * 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.sentry.provider.db.generic.tools;
-
-import com.google.common.io.Files;
-import com.google.common.collect.Sets;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.core.common.exception.SentryConfigurationException;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestSentryConfigToolSolr extends SentryGenericServiceIntegrationBase {
-  private static String RESOURCES_DIR = "target" + File.separator + "test-classes" + File.separator;
-  private static String VALID_POLICY_INI = RESOURCES_DIR + "solr_config_import_tool.ini";
-  private static String INVALID_POLICY_INI = RESOURCES_DIR + "solr_invalid.ini";
-  private static String CASE_POLICY_INI = RESOURCES_DIR + "solr_case.ini";
-  private File confDir;
-  private File confPath;
-  private String requestorName = "";
-  private String service = "service1";
-
-  @Before
-  public void prepareForTest() throws Exception {
-    confDir = Files.createTempDir();
-    confPath = new File(confDir, "sentry-site.xml");
-    if (confPath.createNewFile()) {
-      FileOutputStream to = new FileOutputStream(confPath);
-      conf.writeXml(to);
-      to.close();
-    }
-    requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
-    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
-    setLocalGroupMapping(requestorName, requestorUserGroupNames);
-    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
-    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
-    writePolicyFile();
-  }
-
-  @After
-  public void clearTestData() throws Exception {
-    FileUtils.deleteQuietly(confDir);
-
-    // clear roles and privileges
-    Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
-    for (TSentryRole tRole : tRoles) {
-      String role = tRole.getRoleName();
-      Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
-          requestorName, role, SOLR, service);
-      for (TSentryPrivilege privilege : privileges) {
-        client.revokePrivilege(requestorName, role, SOLR, privilege);
-      }
-      client.dropRole(requestorName, role, SOLR);
-    }
-  }
-
-  @Test
-  public void testConvertIni() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
-        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
-        sentryTool.executeConfigTool(args);
-
-        Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
-        groupMapping.put("corporal_role", Sets.newHashSet("corporal", "sergeant", "general", "commander_in_chief"));
-        groupMapping.put("sergeant_role", Sets.newHashSet("sergeant", "general", "commander_in_chief"));
-        groupMapping.put("general_role", Sets.newHashSet("general", "commander_in_chief"));
-        groupMapping.put("commander_in_chief_role", Sets.newHashSet("commander_in_chief"));
-
-        Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
-        privilegeMapping.put("corporal_role",
-            Sets.newHashSet("Collection=info->action=query", "Collection=info->action=update"));
-        privilegeMapping.put("sergeant_role",
-            Sets.newHashSet("Collection=info->action=update"));
-        privilegeMapping.put("general_role",
-            Sets.newHashSet("Collection=info->action=*"));
-        privilegeMapping.put("commander_in_chief_role",
-            Sets.newHashSet("Collection=*->action=*"));
-
-        // check roles
-        Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
-        assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
-        Set<String> roles = new HashSet<String>();
-        for (TSentryRole tRole : tRoles) {
-          roles.add(tRole.getRoleName());
-        }
-
-        for (String expectedRole : groupMapping.keySet()) {
-          assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
-        }
-
-        // check groups
-        for (TSentryRole tRole : tRoles) {
-          Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
-          assertEquals("Group size doesn't match for role: " + tRole.getRoleName(),
-              expectedGroups.size(), tRole.getGroups().size());
-          assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
-              tRole.getGroups().containsAll(expectedGroups));
-        }
-
-        // check privileges
-        GenericPrivilegeConverter convert = new GenericPrivilegeConverter(SOLR, service);
-        for (String role : roles) {
-          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
-              requestorName, role, SOLR, service);
-          Set<String> expectedPrivileges = privilegeMapping.get(role);
-          assertEquals("Privilege set size doesn't match for role: " + role,
-              expectedPrivileges.size(), privileges.size());
-
-          Set<String> privilegeStrs = new HashSet<String>();
-          for (TSentryPrivilege privilege : privileges) {
-            privilegeStrs.add(convert.toString(privilege));
-          }
-
-          for (String expectedPrivilege : expectedPrivileges) {
-            assertTrue("Did not find expected privilege: " + expectedPrivilege + " in " + privilegeStrs,
-                privilegeStrs.contains(expectedPrivilege));
-          }
-        }
-      }
-    });
-  }
-
-  @Test
-  public void testNoPolicyFile() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        String[] args = { "-p", INVALID_POLICY_INI + "Foobar", "-conf", confPath.getAbsolutePath(), "-v", "-i"};
-        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
-        try {
-          sentryTool.executeConfigTool(args);
-          fail("Exception should be thrown for nonexistant ini");
-        } catch (SentryConfigurationException e) {
-          // expected exception
-        }
-      }
-    });
-  }
-
-  @Test
-  public void testNoValidateNorImport() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath()};
-        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
-        try {
-          sentryTool.executeConfigTool(args);
-          fail("Exception should be thrown for validating invalid ini");
-        } catch (IllegalArgumentException e) {
-          // expected exception
-        }
-      }
-    });
-  }
-
-  @Test
-  public void testConvertInvalidIni() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // test: validate an invalid ini
-        String[] args = { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i"};
-        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
-        try {
-          sentryTool.executeConfigTool(args);
-          fail("Exception should be thrown for validating invalid ini");
-        } catch (SentryConfigurationException e) {
-          // expected exception
-        }
-
-        // test without validating, should not error
-        args = new String[] { "-p", INVALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i"};
-        sentryTool = new SentryConfigToolSolr();
-        sentryTool.executeConfigTool(args);
-      }
-    });
-  }
-
-  @Test
-  public void testCompatCheck() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // test: validate an invalid ini
-        String[] args = { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
-        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
-        try {
-          sentryTool.executeConfigTool(args);
-          fail("Exception should be thrown for validating invalid ini");
-        } catch (SentryConfigurationException e) {
-          assertEquals("Expected error", 1, e.getConfigErrors().size());
-          String error = e.getConfigErrors().get(0);
-          assertCasedRoleNamesInMessage(error, "RoLe1", "rOlE1");
-          String warning = e.getConfigWarnings().get(0);
-          assertCasedRoleNamesInMessage(warning, "ROLE2", "RoLe1", "rOlE1");
-          assertEquals("Expected warning", 1, e.getConfigWarnings().size());
-        }
-
-        // test without compat checking
-        args = new String[] { "-p", CASE_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-i", "-v"};
-        sentryTool = new SentryConfigToolSolr();
-        sentryTool.executeConfigTool(args);
-      }
-    });
-  }
-
-  // Test that a valid compat check doesn't throw an exception
-  @Test
-  public void testCompatCheckValid() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        String[] args = { "-p", VALID_POLICY_INI, "-conf", confPath.getAbsolutePath(), "-v", "-i", "-c"};
-        SentryConfigToolSolr sentryTool = new SentryConfigToolSolr();
-        sentryTool.executeConfigTool(args);
-      }
-    });
-  }
-
-  private void assertCasedRoleNamesInMessage(String message, String ... casedRoleNames) {
-    for (String casedRoleName : casedRoleNames) {
-      assertTrue("Expected cased role name: " + casedRoleName, message.contains(casedRoleName));
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellIndexer.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellIndexer.java
deleted file mode 100644
index f66eb85..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellIndexer.java
+++ /dev/null
@@ -1,526 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import com.google.common.collect.Sets;
-import com.google.common.io.Files;
-import org.apache.commons.io.FileUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.tools.SentryShellCommon;
-import org.apache.sentry.service.thrift.ServiceConstants;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import static junit.framework.Assert.assertEquals;
-import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-public class TestSentryShellIndexer extends SentryGenericServiceIntegrationBase {
-  private File confDir;
-  private File confPath;
-  private static String TEST_ROLE_NAME_1 = "testRole1";
-  private static String TEST_ROLE_NAME_2 = "testRole2";
-  private String requestorName = "";
-  private String service = "service1";
-
-  @Before
-  public void prepareForTest() throws Exception {
-    confDir = Files.createTempDir();
-    confPath = new File(confDir, "sentry-site.xml");
-    conf.set(ServiceConstants.ClientConfig.SERVICE_NAME, service);
-    if (confPath.createNewFile()) {
-      FileOutputStream to = new FileOutputStream(confPath);
-      conf.writeXml(to);
-      to.close();
-    }
-    requestorName = clientUgi.getShortUserName();
-    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
-    setLocalGroupMapping(requestorName, requestorUserGroupNames);
-    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
-    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
-    writePolicyFile();
-  }
-
-  @After
-  public void clearTestData() throws Exception {
-    FileUtils.deleteQuietly(confDir);
-  }
-
-  @Test
-  public void testCreateDropRole() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // test: create role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-        // test: create role with --create_role
-        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-
-        // validate the result, list roles with -lr
-        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() };
-        SentryShellIndexer sentryShell = new SentryShellIndexer();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // validate the result, list roles with --list_role
-        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // test: drop role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-        // test: drop role with --drop_role
-        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listAllRoles(requestorName, HBASE_INDEXER);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-      }
-    });
-  }
-
-  @Test
-  public void testAddDeleteRoleForGroup() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // Group names are case sensitive - mixed case names should work
-        String TEST_GROUP_1 = "testGroup1";
-        String TEST_GROUP_2 = "testGroup2";
-        String TEST_GROUP_3 = "testGroup3";
-
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
-        client.createRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
-        // test: add role to group with -arg
-        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-        // test: add role to multiple groups
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
-            "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-        // test: add role to group with --add_role_group
-        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
-            "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-
-        // validate the result list roles with -lr and -g
-        args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath() };
-        SentryShellIndexer sentryShell = new SentryShellIndexer();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // list roles with --list_role and -g
-        args = new String[] { "--list_role", "-g", TEST_GROUP_2, "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        // test: delete role from group with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-        // test: delete role to multiple groups
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
-            "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-        // test: delete role from group with --delete_role_group
-        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
-            "-conf", confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, HBASE_INDEXER);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, HBASE_INDEXER);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, HBASE_INDEXER);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
-      }
-    });
-  }
-
-  @Test
-  public void testCaseSensitiveGroupName() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
-        // add role to a group (lower case)
-        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellIndexer.main(args);
-
-        // validate the roles when group name is same case as above
-        args = new String[] { "-lr", "-g", "group1", "-conf", confPath.getAbsolutePath() };
-        SentryShellIndexer sentryShell = new SentryShellIndexer();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        // roles should be empty when group name is different case than above
-        args = new String[] { "-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath() };
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames);
-      }
-      });
-    }
-
-  public static String grant(boolean shortOption) {
-    return shortOption ? "-gpr" : "--grant_privilege_role";
-  }
-
-  public static String revoke(boolean shortOption) {
-    return shortOption ? "-rpr" : "--revoke_privilege_role";
-  }
-
-  public static String list(boolean shortOption) {
-    return shortOption ? "-lp" : "--list_privilege";
-  }
-
-  private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
-        client.createRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
-
-        String [] privs = {
-          "Indexer=*->action=*",
-          "Indexer=indexer1->action=read",
-          "Indexer=indexer2->action=write"
-        };
-        for (int i = 0; i < privs.length; ++i) {
-          // test: grant privilege to role
-          String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
-            privs[ i ],
-            "-conf", confPath.getAbsolutePath() };
-          SentryShellIndexer.main(args);
-        }
-
-        // test the list privilege
-        String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        SentryShellIndexer sentryShell = new SentryShellIndexer();
-        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
-        assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
-        for (int i = 0; i < privs.length; ++i) {
-          assertTrue("Expected privilege: " + privs[ i ], privilegeStrs.contains(privs[ i ]));
-        }
-
-        for (int i = 0; i < privs.length; ++i) {
-          args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
-            privs[ i ], "-conf",
-            confPath.getAbsolutePath() };
-          SentryShellIndexer.main(args);
-          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
-            TEST_ROLE_NAME_1, HBASE_INDEXER, service);
-          assertEquals("Incorrect number of privileges", privs.length - (i + 1), privileges.size());
-        }
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
-      }
-    });
-  }
-
-
-  @Test
-  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
-    assertGrantRevokePrivilege(true);
-  }
-
-  @Test
-  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
-    assertGrantRevokePrivilege(false);
-  }
-
-  @Test
-  public void testNegativeCaseWithInvalidArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
-        // test: create duplicate role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        SentryShellIndexer sentryShell = new SentryShellIndexer();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for creating duplicate role");
-        } catch (SentryUserException e) {
-          // expected exception
-        }
-
-        // test: drop non-exist role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for dropping non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: add non-exist role to group with -arg
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for granting non-exist role to group");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: drop group from non-exist role with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for drop group from non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: grant privilege to role with the error privilege format
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=*",
-            "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for the error privilege format, invalid key value.");
-        } catch (IllegalArgumentException e) {
-          // excepted exception
-        }
-
-        // test: grant privilege to role with the error privilege hierarchy
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->table=tbl1->column=col2->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for the error privilege format, invalid key value.");
-        } catch (IllegalArgumentException e) {
-          // expected exception
-        }
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
-      }
-    });
-  }
-
-  @Test
-  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        String strOptionConf = "conf";
-        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
-        // test: the conf is required argument
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1 };
-        SentryShellIndexer sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
-
-        // test: -r is required when create role
-        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when drop role
-        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when add role to group
-        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when add role to group
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when delete role from group
-        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when delete role from group
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when grant privilege to role
-        args = new String[] { "-gpr", "-p", "indexer=Indexer1", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when grant privilege to role
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: action is required in privilege
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "indexer=Indexer1" };
-        sentryShell = new SentryShellIndexer();
-         try {
-          getShellResultWithOSRedirect(sentryShell, args, false);
-          fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-          assert("Privilege is invalid: action required but not specified.".equals(e.getMessage()));
-        }
-
-        // test: -r is required when revoke privilege from role
-        args = new String[] { "-rpr", "-p", "indexer=Indexer1", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when revoke privilege from role
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: command option is required for shell
-        args = new String[] {"-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellIndexer();
-        validateMissingParameterMsgsContains(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
-                "-arg Add role to group",
-                "-cr Create role",
-                "-rpr Revoke privilege from role",
-                "-drg Delete role from group",
-                "-lr List role",
-                "-lp List privilege",
-                "-gpr Grant privilege to role",
-                "-dr Drop role");
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
-      }
-    });
-  }
-
-  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
-  private Set<String> getShellResultWithOSRedirect(SentryShellIndexer sentryShell,
-      String[] args, boolean expectedExecuteResult) throws Exception {
-    PrintStream oldOut = System.out;
-    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
-    System.setOut(new PrintStream(outContent));
-    assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
-    String outContentStr = outContent.toString();
-    Set<String> resultSet = outContentStr.length() > 0 ? Sets.<String>newHashSet(outContentStr.split("\n")) : Sets.<String>newHashSet();
-    System.setOut(oldOut);
-    return resultSet;
-  }
-
-  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
-    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
-      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
-          expectedRoleNames.length, roleNames.size());
-      Set<String> lowerCaseRoles = new HashSet<String>();
-      for (String role : roleNames) {
-        lowerCaseRoles.add(role.toLowerCase());
-      }
-
-      for (String expectedRole : expectedRoleNames) {
-        assertTrue("Expected role: " + expectedRole,
-            lowerCaseRoles.contains(expectedRole.toLowerCase()));
-      }
-    }
-  }
-
-  private void validateMissingParameterMsg(SentryShellIndexer sentryShell, String[] args,
-      String expectedErrorMsg) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
-  }
-
-  private void validateMissingParameterMsgsContains(SentryShellIndexer sentryShell, String[] args,
-      String ... expectedErrorMsgsContains) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    boolean foundAllMessages = false;
-    Iterator<String> it = errorMsgs.iterator();
-    while (it.hasNext()) {
-      String errorMessage = it.next();
-      boolean missingExpected = false;
-      for (String expectedContains : expectedErrorMsgsContains) {
-        if (!errorMessage.contains(expectedContains)) {
-          missingExpected = true;
-          break;
-        }
-      }
-      if (!missingExpected) {
-        foundAllMessages = true;
-        break;
-      }
-    }
-    assertTrue(foundAllMessages);
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java
deleted file mode 100644
index a9234fa..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellKafka.java
+++ /dev/null
@@ -1,550 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import com.google.common.collect.Sets;
-import com.google.common.io.Files;
-import org.apache.commons.io.FileUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.core.model.kafka.validator.KafkaPrivilegeValidator;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.tools.SentryShellCommon;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import static org.junit.Assert.*;
-
-public class TestSentryShellKafka extends SentryGenericServiceIntegrationBase {
-  private File confDir;
-  private File confPath;
-  private static String TEST_ROLE_NAME_1 = "testRole1";
-  private static String TEST_ROLE_NAME_2 = "testRole2";
-  private static String KAFKA = "kafka";
-  private String requestorName = "";
-  private String service = "kafka";
-
-  @Before
-  public void prepareForTest() throws Exception {
-    confDir = Files.createTempDir();
-    confPath = new File(confDir, "sentry-site.xml");
-    if (confPath.createNewFile()) {
-      FileOutputStream to = new FileOutputStream(confPath);
-      conf.writeXml(to);
-      to.close();
-    }
-    requestorName = clientUgi.getShortUserName();//.getProperty("user.name", "");
-    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
-    setLocalGroupMapping(requestorName, requestorUserGroupNames);
-    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
-    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
-    writePolicyFile();
-  }
-
-  @After
-  public void clearTestData() throws Exception {
-    FileUtils.deleteQuietly(confDir);
-  }
-
-  @Test
-  public void testCreateDropRole() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // test: create role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-        // test: create role with --create_role
-        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-
-        // validate the result, list roles with -lr
-        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // validate the result, list roles with --list_role
-        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // test: drop role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-        // test: drop role with --drop_role
-        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listAllRoles(requestorName, KAFKA);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-      }
-    });
-  }
-
-  @Test
-  public void testAddDeleteRoleForGroup() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // Group names are case sensitive - mixed case names should work
-        String TEST_GROUP_1 = "testGroup1";
-        String TEST_GROUP_2 = "testGroup2";
-        String TEST_GROUP_3 = "testGroup3";
-
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
-        client.createRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
-        // test: add role to group with -arg
-        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-        // test: add role to multiple groups
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
-            "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-        // test: add role to group with --add_role_group
-        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
-            "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-
-        // validate the result list roles with -lr and -g
-        args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // list roles with --list_role and -g
-        args = new String[] { "--list_role", "-g", TEST_GROUP_2, "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        // List the groups and roles via listGroups
-        args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true);
-        assertEquals(3, groups.size());
-        assertTrue(groups.contains("testGroup3 = testrole1"));
-        assertTrue(groups.contains("testGroup2 = testrole1"));
-        assertTrue(groups.contains("testGroup1 = testrole2, testrole1"));
-
-        // test: delete role from group with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-        // test: delete role to multiple groups
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
-            "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-        // test: delete role from group with --delete_role_group
-        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
-            "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, KAFKA);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, KAFKA);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, KAFKA);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
-      }
-    });
-  }
-
-  @Test
-  public void testCaseSensitiveGroupName() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
-        // add role to a group (lower case)
-        String[] args = {"-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka"};
-        SentryShellGeneric.main(args);
-
-        // validate the roles when group name is same case as above
-        args = new String[]{"-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "kafka"};
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        // roles should be empty when group name is different case than above
-        args = new String[]{"-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "kafka"};
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames);
-      }
-    });
-  }
-
-  public static String grant(boolean shortOption) {
-    return shortOption ? "-gpr" : "--grant_privilege_role";
-  }
-
-  public static String revoke(boolean shortOption) {
-    return shortOption ? "-rpr" : "--revoke_privilege_role";
-  }
-
-  public static String list(boolean shortOption) {
-    return shortOption ? "-lp" : "--list_privilege";
-  }
-
-  private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
-        client.createRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
-
-        String [] privs = {
-            "HOST=*->CLUSTER=kafka-cluster->action=read",
-            "HOST=h1->TOPIC=t1->action=write",
-            "HOST=*->CONSUMERGROUP=cg1->action=read",
-            "CLUSTER=kafka-cluster->action=write",
-            "CONSUMERGROUP=cg2->action=write"
-        };
-        for (int i = 0; i < privs.length; ++i) {
-          // test: grant privilege to role
-          String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
-            privs[ i ],
-            "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-          SentryShellGeneric.main(args);
-        }
-
-        // test the list privilege
-        String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
-
-        assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
-        for (int i = 0; i < privs.length; ++i) {
-          assertTrue("Expected privilege: " + privs[i] + " in " + Arrays.toString(privilegeStrs.toArray()), privilegeStrs.contains(privs[i].startsWith("HOST=") ? privs[i] : "HOST=*->" + privs[i]));
-        }
-
-        for (int i = 0; i < privs.length; ++i) {
-          args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
-            privs[ i ], "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-          SentryShellGeneric.main(args);
-          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
-            TEST_ROLE_NAME_1, KAFKA, service);
-          assertEquals("Incorrect number of privileges. Received privileges: " + Arrays.toString(privileges.toArray()), privs.length - (i + 1), privileges.size());
-        }
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
-      }
-    });
-  }
-
-
-  @Test
-  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
-    assertGrantRevokePrivilege(true);
-  }
-
-  @Test
-  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
-    assertGrantRevokePrivilege(false);
-  }
-
-
-  @Test
-  public void testNegativeCaseWithInvalidArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
-        // test: create duplicate role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for creating duplicate role");
-        } catch (SentryUserException e) {
-          // expected exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // test: drop non-exist role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for dropping non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // test: add non-exist role to group with -arg
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for granting non-exist role to group");
-        } catch (SentryUserException e) {
-          // excepted exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // test: drop group from non-exist role with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for drop group from non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // test: grant privilege to role with the error privilege format
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=all",
-            "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for the error privilege format, invalid key value.");
-        } catch (IllegalArgumentException e) {
-          // excepted exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // test: grant privilege to role with the error privilege hierarchy
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "consumergroup=cg1->host=h1->action=create", "-conf",
-            confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for the error privilege format, invalid key value.");
-        } catch (IllegalArgumentException e) {
-          // expected exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
-      }
-    });
-  }
-
-  @Test
-  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        String strOptionConf = "conf";
-        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
-        // test: the conf is required argument
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "kafka" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
-
-        // test: -r is required when create role
-        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when drop role
-        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when add role to group
-        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when add role to group
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when delete role from group
-        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when delete role from group
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when grant privilege to role
-        args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when grant privilege to role
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: action is required in privilege
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "host=*->topic=t1", "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-         try {
-          getShellResultWithOSRedirect(sentryShell, args, false);
-          fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-           assert(("Kafka privilege must end with a valid action.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg).equals(e.getCause().getMessage()));
-        } catch (Exception e) {
-           fail ("Unexpected exception received. " + e);
-         }
-
-        // test: -r is required when revoke privilege from role
-        args = new String[] { "-rpr", "-p", "host=h1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when revoke privilege from role
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: command option is required for shell
-        args = new String[] {"-conf", confPath.getAbsolutePath(), "-t", "kafka" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsgsContains(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
-                "-arg Add role to group",
-                "-cr Create role",
-                "-rpr Revoke privilege from role",
-                "-drg Delete role from group",
-                "-lr List role",
-                "-lp List privilege",
-                "-gpr Grant privilege to role",
-                "-dr Drop role");
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
-      }
-    });
-  }
-
-  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
-  private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
-      String[] args, boolean expectedExecuteResult) throws Exception {
-    PrintStream oldOut = System.out;
-    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
-    System.setOut(new PrintStream(outContent));
-    assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
-    Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n"));
-    System.setOut(oldOut);
-    return resultSet;
-  }
-
-  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
-    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
-      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
-          expectedRoleNames.length, roleNames.size());
-      Set<String> lowerCaseRoles = new HashSet<String>();
-      for (String role : roleNames) {
-        lowerCaseRoles.add(role.toLowerCase());
-      }
-
-      for (String expectedRole : expectedRoleNames) {
-        assertTrue("Expected role: " + expectedRole,
-            lowerCaseRoles.contains(expectedRole.toLowerCase()));
-      }
-    }
-  }
-
-  private void validateMissingParameterMsg(SentryShellGeneric sentryShell, String[] args,
-      String expectedErrorMsg) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
-  }
-
-  private void validateMissingParameterMsgsContains(SentryShellGeneric sentryShell, String[] args,
-      String ... expectedErrorMsgsContains) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    boolean foundAllMessages = false;
-    Iterator<String> it = errorMsgs.iterator();
-    while (it.hasNext()) {
-      String errorMessage = it.next();
-      boolean missingExpected = false;
-      for (String expectedContains : expectedErrorMsgsContains) {
-        if (!errorMessage.contains(expectedContains)) {
-          missingExpected = true;
-          break;
-        }
-      }
-      if (!missingExpected) {
-        foundAllMessages = true;
-        break;
-      }
-    }
-    assertTrue(foundAllMessages);
-  }
-}


[2/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.

Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellIndexer.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellIndexer.java
new file mode 100644
index 0000000..f31d7b7
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellIndexer.java
@@ -0,0 +1,525 @@
+/**
+ * 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.sentry.cli.tools;
+
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.apache.sentry.service.thrift.ServiceConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import static junit.framework.Assert.assertEquals;
+import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class TestSentryShellIndexer extends SentryGenericServiceIntegrationBase {
+  private File confDir;
+  private File confPath;
+  private static String TEST_ROLE_NAME_1 = "testRole1";
+  private static String TEST_ROLE_NAME_2 = "testRole2";
+  private String requestorName = "";
+  private String service = "service1";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    conf.set(ServiceConstants.ClientConfig.SERVICE_NAME, service);
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+  }
+
+  @Test
+  public void testCreateDropRole() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: create role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+        // test: create role with --create_role
+        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+
+        // validate the result, list roles with -lr
+        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() };
+        SentryShellIndexer sentryShell = new SentryShellIndexer();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // validate the result, list roles with --list_role
+        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // test: drop role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+        // test: drop role with --drop_role
+        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listAllRoles(requestorName, HBASE_INDEXER);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+      }
+    });
+  }
+
+  @Test
+  public void testAddDeleteRoleForGroup() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // Group names are case sensitive - mixed case names should work
+        String TEST_GROUP_1 = "testGroup1";
+        String TEST_GROUP_2 = "testGroup2";
+        String TEST_GROUP_3 = "testGroup3";
+
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+        client.createRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
+        // test: add role to group with -arg
+        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+        // test: add role to multiple groups
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+        // test: add role to group with --add_role_group
+        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+
+        // validate the result list roles with -lr and -g
+        args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellIndexer sentryShell = new SentryShellIndexer();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // list roles with --list_role and -g
+        args = new String[] { "--list_role", "-g", TEST_GROUP_2, "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // test: delete role from group with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+        // test: delete role to multiple groups
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+            "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+        // test: delete role from group with --delete_role_group
+        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+            "-conf", confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, HBASE_INDEXER);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, HBASE_INDEXER);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, HBASE_INDEXER);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
+      }
+    });
+  }
+
+  @Test
+  public void testCaseSensitiveGroupName() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+        // add role to a group (lower case)
+        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
+            confPath.getAbsolutePath() };
+        SentryShellIndexer.main(args);
+
+        // validate the roles when group name is same case as above
+        args = new String[] { "-lr", "-g", "group1", "-conf", confPath.getAbsolutePath() };
+        SentryShellIndexer sentryShell = new SentryShellIndexer();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // roles should be empty when group name is different case than above
+        args = new String[] { "-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath() };
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames);
+      }
+      });
+    }
+
+  public static String grant(boolean shortOption) {
+    return shortOption ? "-gpr" : "--grant_privilege_role";
+  }
+
+  public static String revoke(boolean shortOption) {
+    return shortOption ? "-rpr" : "--revoke_privilege_role";
+  }
+
+  public static String list(boolean shortOption) {
+    return shortOption ? "-lp" : "--list_privilege";
+  }
+
+  private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+        client.createRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
+
+        String [] privs = {
+          "Indexer=*->action=*",
+          "Indexer=indexer1->action=read",
+          "Indexer=indexer2->action=write"
+        };
+        for (int i = 0; i < privs.length; ++i) {
+          // test: grant privilege to role
+          String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+            privs[ i ],
+            "-conf", confPath.getAbsolutePath() };
+          SentryShellIndexer.main(args);
+        }
+
+        // test the list privilege
+        String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellIndexer sentryShell = new SentryShellIndexer();
+        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+        assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
+        for (int i = 0; i < privs.length; ++i) {
+          assertTrue("Expected privilege: " + privs[ i ], privilegeStrs.contains(privs[ i ]));
+        }
+
+        for (int i = 0; i < privs.length; ++i) {
+          args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+            privs[ i ], "-conf",
+            confPath.getAbsolutePath() };
+          SentryShellIndexer.main(args);
+          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+            TEST_ROLE_NAME_1, HBASE_INDEXER, service);
+          assertEquals("Incorrect number of privileges", privs.length - (i + 1), privileges.size());
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2, HBASE_INDEXER);
+      }
+    });
+  }
+
+
+  @Test
+  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+    assertGrantRevokePrivilege(true);
+  }
+
+  @Test
+  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+    assertGrantRevokePrivilege(false);
+  }
+
+  @Test
+  public void testNegativeCaseWithInvalidArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+        // test: create duplicate role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        SentryShellIndexer sentryShell = new SentryShellIndexer();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for creating duplicate role");
+        } catch (SentryUserException e) {
+          // expected exception
+        }
+
+        // test: drop non-exist role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for dropping non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: add non-exist role to group with -arg
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for granting non-exist role to group");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: drop group from non-exist role with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for drop group from non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: grant privilege to role with the error privilege format
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=*",
+            "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // excepted exception
+        }
+
+        // test: grant privilege to role with the error privilege hierarchy
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->table=tbl1->column=col2->action=insert", "-conf",
+            confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // expected exception
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+      }
+    });
+  }
+
+  @Test
+  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String strOptionConf = "conf";
+        client.createRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+        // test: the conf is required argument
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1 };
+        SentryShellIndexer sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
+
+        // test: -r is required when create role
+        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when drop role
+        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when add role to group
+        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when add role to group
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when delete role from group
+        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when delete role from group
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when grant privilege to role
+        args = new String[] { "-gpr", "-p", "indexer=Indexer1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when grant privilege to role
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: action is required in privilege
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "indexer=Indexer1" };
+        sentryShell = new SentryShellIndexer();
+         try {
+          getShellResultWithOSRedirect(sentryShell, args, false);
+          fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+          assert("Privilege is invalid: action required but not specified.".equals(e.getMessage()));
+        }
+
+        // test: -r is required when revoke privilege from role
+        args = new String[] { "-rpr", "-p", "indexer=Indexer1", "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when revoke privilege from role
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: command option is required for shell
+        args = new String[] {"-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellIndexer();
+        validateMissingParameterMsgsContains(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
+                "-arg Add role to group",
+                "-cr Create role",
+                "-rpr Revoke privilege from role",
+                "-drg Delete role from group",
+                "-lr List role",
+                "-lp List privilege",
+                "-gpr Grant privilege to role",
+                "-dr Drop role");
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, HBASE_INDEXER);
+      }
+    });
+  }
+
+  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+  private Set<String> getShellResultWithOSRedirect(SentryShellIndexer sentryShell,
+      String[] args, boolean expectedExecuteResult) throws Exception {
+    PrintStream oldOut = System.out;
+    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+    System.setOut(new PrintStream(outContent));
+    assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
+    String outContentStr = outContent.toString();
+    Set<String> resultSet = outContentStr.length() > 0 ? Sets.<String>newHashSet(outContentStr.split("\n")) : Sets.<String>newHashSet();
+    System.setOut(oldOut);
+    return resultSet;
+  }
+
+  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
+    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
+      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
+          expectedRoleNames.length, roleNames.size());
+      Set<String> lowerCaseRoles = new HashSet<String>();
+      for (String role : roleNames) {
+        lowerCaseRoles.add(role.toLowerCase());
+      }
+
+      for (String expectedRole : expectedRoleNames) {
+        assertTrue("Expected role: " + expectedRole,
+            lowerCaseRoles.contains(expectedRole.toLowerCase()));
+      }
+    }
+  }
+
+  private void validateMissingParameterMsg(SentryShellIndexer sentryShell, String[] args,
+      String expectedErrorMsg) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
+  }
+
+  private void validateMissingParameterMsgsContains(SentryShellIndexer sentryShell, String[] args,
+      String ... expectedErrorMsgsContains) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    boolean foundAllMessages = false;
+    Iterator<String> it = errorMsgs.iterator();
+    while (it.hasNext()) {
+      String errorMessage = it.next();
+      boolean missingExpected = false;
+      for (String expectedContains : expectedErrorMsgsContains) {
+        if (!errorMessage.contains(expectedContains)) {
+          missingExpected = true;
+          break;
+        }
+      }
+      if (!missingExpected) {
+        foundAllMessages = true;
+        break;
+      }
+    }
+    assertTrue(foundAllMessages);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellKafka.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellKafka.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellKafka.java
new file mode 100644
index 0000000..3b06d90
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellKafka.java
@@ -0,0 +1,549 @@
+/**
+ * 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.sentry.cli.tools;
+
+import com.google.common.collect.Sets;
+import com.google.common.io.Files;
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.core.model.kafka.validator.KafkaPrivilegeValidator;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+public class TestSentryShellKafka extends SentryGenericServiceIntegrationBase {
+  private File confDir;
+  private File confPath;
+  private static String TEST_ROLE_NAME_1 = "testRole1";
+  private static String TEST_ROLE_NAME_2 = "testRole2";
+  private static String KAFKA = "kafka";
+  private String requestorName = "";
+  private String service = "kafka";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();//.getProperty("user.name", "");
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+  }
+
+  @Test
+  public void testCreateDropRole() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: create role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+        // test: create role with --create_role
+        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+
+        // validate the result, list roles with -lr
+        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // validate the result, list roles with --list_role
+        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // test: drop role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+        // test: drop role with --drop_role
+        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listAllRoles(requestorName, KAFKA);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+      }
+    });
+  }
+
+  @Test
+  public void testAddDeleteRoleForGroup() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // Group names are case sensitive - mixed case names should work
+        String TEST_GROUP_1 = "testGroup1";
+        String TEST_GROUP_2 = "testGroup2";
+        String TEST_GROUP_3 = "testGroup3";
+
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+        client.createRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
+        // test: add role to group with -arg
+        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+        // test: add role to multiple groups
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+            "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+        // test: add role to group with --add_role_group
+        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+            "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+
+        // validate the result list roles with -lr and -g
+        args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // list roles with --list_role and -g
+        args = new String[] { "--list_role", "-g", TEST_GROUP_2, "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // List the groups and roles via listGroups
+        args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true);
+        assertEquals(3, groups.size());
+        assertTrue(groups.contains("testGroup3 = testrole1"));
+        assertTrue(groups.contains("testGroup2 = testrole1"));
+        assertTrue(groups.contains("testGroup1 = testrole2, testrole1"));
+
+        // test: delete role from group with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+        // test: delete role to multiple groups
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+            "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+        // test: delete role from group with --delete_role_group
+        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+            "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, KAFKA);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, KAFKA);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, KAFKA);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
+      }
+    });
+  }
+
+  @Test
+  public void testCaseSensitiveGroupName() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+        // add role to a group (lower case)
+        String[] args = {"-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka"};
+        SentryShellGeneric.main(args);
+
+        // validate the roles when group name is same case as above
+        args = new String[]{"-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "kafka"};
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // roles should be empty when group name is different case than above
+        args = new String[]{"-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "kafka"};
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames);
+      }
+    });
+  }
+
+  public static String grant(boolean shortOption) {
+    return shortOption ? "-gpr" : "--grant_privilege_role";
+  }
+
+  public static String revoke(boolean shortOption) {
+    return shortOption ? "-rpr" : "--revoke_privilege_role";
+  }
+
+  public static String list(boolean shortOption) {
+    return shortOption ? "-lp" : "--list_privilege";
+  }
+
+  private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+        client.createRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
+
+        String [] privs = {
+            "HOST=*->CLUSTER=kafka-cluster->action=read",
+            "HOST=h1->TOPIC=t1->action=write",
+            "HOST=*->CONSUMERGROUP=cg1->action=read",
+            "CLUSTER=kafka-cluster->action=write",
+            "CONSUMERGROUP=cg2->action=write"
+        };
+        for (int i = 0; i < privs.length; ++i) {
+          // test: grant privilege to role
+          String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+            privs[ i ],
+            "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+          SentryShellGeneric.main(args);
+        }
+
+        // test the list privilege
+        String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+
+        assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
+        for (int i = 0; i < privs.length; ++i) {
+          assertTrue("Expected privilege: " + privs[i] + " in " + Arrays.toString(privilegeStrs.toArray()), privilegeStrs.contains(privs[i].startsWith("HOST=") ? privs[i] : "HOST=*->" + privs[i]));
+        }
+
+        for (int i = 0; i < privs.length; ++i) {
+          args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+            privs[ i ], "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+          SentryShellGeneric.main(args);
+          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+            TEST_ROLE_NAME_1, KAFKA, service);
+          assertEquals("Incorrect number of privileges. Received privileges: " + Arrays.toString(privileges.toArray()), privs.length - (i + 1), privileges.size());
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2, KAFKA);
+      }
+    });
+  }
+
+
+  @Test
+  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+    assertGrantRevokePrivilege(true);
+  }
+
+  @Test
+  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+    assertGrantRevokePrivilege(false);
+  }
+
+
+  @Test
+  public void testNegativeCaseWithInvalidArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+        // test: create duplicate role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for creating duplicate role");
+        } catch (SentryUserException e) {
+          // expected exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // test: drop non-exist role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for dropping non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // test: add non-exist role to group with -arg
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for granting non-exist role to group");
+        } catch (SentryUserException e) {
+          // excepted exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // test: drop group from non-exist role with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for drop group from non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // test: grant privilege to role with the error privilege format
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=all",
+            "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // excepted exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // test: grant privilege to role with the error privilege hierarchy
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "consumergroup=cg1->host=h1->action=create", "-conf",
+            confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // expected exception
+        } catch (Exception e) {
+          fail ("Unexpected exception received. " + e);
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+      }
+    });
+  }
+
+  @Test
+  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String strOptionConf = "conf";
+        client.createRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+        // test: the conf is required argument
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "kafka" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
+
+        // test: -r is required when create role
+        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when drop role
+        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when add role to group
+        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when add role to group
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when delete role from group
+        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when delete role from group
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when grant privilege to role
+        args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when grant privilege to role
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: action is required in privilege
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "host=*->topic=t1", "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+         try {
+          getShellResultWithOSRedirect(sentryShell, args, false);
+          fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+           assert(("Kafka privilege must end with a valid action.\n" + KafkaPrivilegeValidator.KafkaPrivilegeHelpMsg).equals(e.getCause().getMessage()));
+        } catch (Exception e) {
+           fail ("Unexpected exception received. " + e);
+         }
+
+        // test: -r is required when revoke privilege from role
+        args = new String[] { "-rpr", "-p", "host=h1", "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when revoke privilege from role
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: command option is required for shell
+        args = new String[] {"-conf", confPath.getAbsolutePath(), "-t", "kafka" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsgsContains(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
+                "-arg Add role to group",
+                "-cr Create role",
+                "-rpr Revoke privilege from role",
+                "-drg Delete role from group",
+                "-lr List role",
+                "-lp List privilege",
+                "-gpr Grant privilege to role",
+                "-dr Drop role");
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, KAFKA);
+      }
+    });
+  }
+
+  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+  private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
+      String[] args, boolean expectedExecuteResult) throws Exception {
+    PrintStream oldOut = System.out;
+    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+    System.setOut(new PrintStream(outContent));
+    assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
+    Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n"));
+    System.setOut(oldOut);
+    return resultSet;
+  }
+
+  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
+    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
+      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
+          expectedRoleNames.length, roleNames.size());
+      Set<String> lowerCaseRoles = new HashSet<String>();
+      for (String role : roleNames) {
+        lowerCaseRoles.add(role.toLowerCase());
+      }
+
+      for (String expectedRole : expectedRoleNames) {
+        assertTrue("Expected role: " + expectedRole,
+            lowerCaseRoles.contains(expectedRole.toLowerCase()));
+      }
+    }
+  }
+
+  private void validateMissingParameterMsg(SentryShellGeneric sentryShell, String[] args,
+      String expectedErrorMsg) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
+  }
+
+  private void validateMissingParameterMsgsContains(SentryShellGeneric sentryShell, String[] args,
+      String ... expectedErrorMsgsContains) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    boolean foundAllMessages = false;
+    Iterator<String> it = errorMsgs.iterator();
+    while (it.hasNext()) {
+      String errorMessage = it.next();
+      boolean missingExpected = false;
+      for (String expectedContains : expectedErrorMsgsContains) {
+        if (!errorMessage.contains(expectedContains)) {
+          missingExpected = true;
+          break;
+        }
+      }
+      if (!missingExpected) {
+        foundAllMessages = true;
+        break;
+      }
+    }
+    assertTrue(foundAllMessages);
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSolr.java b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSolr.java
new file mode 100644
index 0000000..b770727
--- /dev/null
+++ b/sentry-tools/src/test/java/org/apache/sentry/cli/tools/TestSentryShellSolr.java
@@ -0,0 +1,533 @@
+/**
+ * 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.sentry.cli.tools;
+
+import com.google.common.io.Files;
+import com.google.common.collect.Sets;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.sentry.core.common.exception.SentryUserException;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestSentryShellSolr extends SentryGenericServiceIntegrationBase {
+  private File confDir;
+  private File confPath;
+  private static String TEST_ROLE_NAME_1 = "testRole1";
+  private static String TEST_ROLE_NAME_2 = "testRole2";
+  private String requestorName = "";
+  private String service = "service1";
+
+  @Before
+  public void prepareForTest() throws Exception {
+    confDir = Files.createTempDir();
+    confPath = new File(confDir, "sentry-site.xml");
+    if (confPath.createNewFile()) {
+      FileOutputStream to = new FileOutputStream(confPath);
+      conf.writeXml(to);
+      to.close();
+    }
+    requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
+    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
+    setLocalGroupMapping(requestorName, requestorUserGroupNames);
+    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
+    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
+    writePolicyFile();
+  }
+
+  @After
+  public void clearTestData() throws Exception {
+    FileUtils.deleteQuietly(confDir);
+  }
+
+  @Test
+  public void testCreateDropRole() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // test: create role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+        // test: create role with --create_role
+        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+
+        // validate the result, list roles with -lr
+        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // validate the result, list roles with --list_role
+        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // test: drop role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+        // test: drop role with --drop_role
+        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listAllRoles(requestorName, SOLR);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+      }
+    });
+  }
+
+  @Test
+  public void testAddDeleteRoleForGroup() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // Group names are case sensitive - mixed case names should work
+        String TEST_GROUP_1 = "testGroup1";
+        String TEST_GROUP_2 = "testGroup2";
+        String TEST_GROUP_3 = "testGroup3";
+
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+        client.createRole(requestorName, TEST_ROLE_NAME_2, SOLR);
+        // test: add role to group with -arg
+        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+        // test: add role to multiple groups
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+            "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+        // test: add role to group with --add_role_group
+        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+            "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+
+        // validate the result list roles with -lr and -g
+        args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
+
+        // list roles with --list_role and -g
+        args = new String[] { "--list_role", "-g", TEST_GROUP_2, "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // List the groups and roles via listGroups
+        args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true);
+        assertEquals(3, groups.size());
+        assertTrue(groups.contains("testGroup3 = testrole1"));
+        assertTrue(groups.contains("testGroup2 = testrole1"));
+        assertTrue(groups.contains("testGroup1 = testrole2, testrole1"));
+
+        // test: delete role from group with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+        // test: delete role to multiple groups
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
+            "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+        // test: delete role from group with --delete_role_group
+        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
+            "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+
+        // validate the result
+        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, SOLR);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, SOLR);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, SOLR);
+        assertEquals("Incorrect number of roles", 0, roles.size());
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2, SOLR);
+      }
+    });
+  }
+
+  @Test
+  public void testCaseSensitiveGroupName() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+        // add role to a group (lower case)
+        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric.main(args);
+
+        // validate the roles when group name is same case as above
+        args = new String[] { "-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
+
+        // roles should be empty when group name is different case than above
+        args = new String[] { "-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
+        validateRoleNames(roleNames);
+      }
+      });
+    }
+
+  public static String grant(boolean shortOption) {
+    return shortOption ? "-gpr" : "--grant_privilege_role";
+  }
+
+  public static String revoke(boolean shortOption) {
+    return shortOption ? "-rpr" : "--revoke_privilege_role";
+  }
+
+  public static String list(boolean shortOption) {
+    return shortOption ? "-lp" : "--list_privilege";
+  }
+
+  private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        // create the role for test
+        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+        client.createRole(requestorName, TEST_ROLE_NAME_2, SOLR);
+
+        String [] privs = {
+          "Collection=*->action=*",
+          "Collection=collection2->action=update",
+          "Collection=collection3->action=query",
+        };
+        for (int i = 0; i < privs.length; ++i) {
+          // test: grant privilege to role
+          String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+            privs[ i ],
+            "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+          SentryShellGeneric.main(args);
+        }
+
+        // test the list privilege
+        String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
+        assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
+        for (int i = 0; i < privs.length; ++i) {
+          assertTrue("Expected privilege: " + privs[ i ], privilegeStrs.contains(privs[ i ]));
+        }
+
+        for (int i = 0; i < privs.length; ++i) {
+          args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
+            privs[ i ], "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+          SentryShellGeneric.main(args);
+          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
+            TEST_ROLE_NAME_1, SOLR, service);
+          assertEquals("Incorrect number of privileges", privs.length - (i + 1), privileges.size());
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+        client.dropRole(requestorName, TEST_ROLE_NAME_2, SOLR);
+      }
+    });
+  }
+
+
+  @Test
+  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
+    assertGrantRevokePrivilege(true);
+  }
+
+  @Test
+  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
+    assertGrantRevokePrivilege(false);
+  }
+
+
+  @Test
+  public void testNegativeCaseWithInvalidArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+        // test: create duplicate role with -cr
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for creating duplicate role");
+        } catch (SentryUserException e) {
+          // expected exception
+        }
+
+        // test: drop non-exist role with -dr
+        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for dropping non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: add non-exist role to group with -arg
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for granting non-exist role to group");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: drop group from non-exist role with -drg
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for drop group from non-exist role");
+        } catch (SentryUserException e) {
+          // excepted exception
+        }
+
+        // test: grant privilege to role with the error privilege format
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=*",
+            "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // excepted exception
+        }
+
+        // test: grant privilege to role with the error privilege hierarchy
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
+            "server=server1->table=tbl1->column=col2->action=insert", "-conf",
+            confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        try {
+          sentryShell.executeShell(args);
+          fail("Exception should be thrown for the error privilege format, invalid key value.");
+        } catch (IllegalArgumentException e) {
+          // expected exception
+        }
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+      }
+    });
+  }
+
+  @Test
+  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
+    runTestAsSubject(new TestOperation() {
+      @Override
+      public void runTestAsSubject() throws Exception {
+        String strOptionConf = "conf";
+        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+        // test: the conf is required argument
+        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "solr" };
+        SentryShellGeneric sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
+
+        // test: -r is required when create role
+        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when drop role
+        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -r is required when add role to group
+        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when add role to group
+        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when delete role from group
+        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -g is required when delete role from group
+        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
+
+        // test: -r is required when grant privilege to role
+        args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when grant privilege to role
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: action is required in privilege
+        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "collection=collection1", "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+         try {
+          getShellResultWithOSRedirect(sentryShell, args, false);
+          fail("Expected IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+          assertEquals("Privilege is invalid: action required but not specified.", e.getMessage());
+        }
+
+        // test: -r is required when revoke privilege from role
+        args = new String[] { "-rpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
+
+        // test: -p is required when revoke privilege from role
+        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsg(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
+
+        // test: command option is required for shell
+        args = new String[] {"-conf", confPath.getAbsolutePath() };
+        sentryShell = new SentryShellGeneric();
+        validateMissingParameterMsgsContains(sentryShell, args,
+                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
+                "-arg Add role to group",
+                "-cr Create role",
+                "-rpr Revoke privilege from role",
+                "-drg Delete role from group",
+                "-lr List role",
+                "-lp List privilege",
+                "-gpr Grant privilege to role",
+                "-dr Drop role");
+
+        // clear the test data
+        client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
+      }
+    });
+  }
+
+  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
+  private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
+      String[] args, boolean expectedExecuteResult) throws Exception {
+    PrintStream oldOut = System.out;
+    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+    System.setOut(new PrintStream(outContent));
+    assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
+    Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n"));
+    System.setOut(oldOut);
+    return resultSet;
+  }
+
+  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
+    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
+      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
+          expectedRoleNames.length, roleNames.size());
+      Set<String> lowerCaseRoles = new HashSet<String>();
+      for (String role : roleNames) {
+        lowerCaseRoles.add(role.toLowerCase());
+      }
+
+      for (String expectedRole : expectedRoleNames) {
+        assertTrue("Expected role: " + expectedRole,
+            lowerCaseRoles.contains(expectedRole.toLowerCase()));
+      }
+    }
+  }
+
+  private void validateMissingParameterMsg(SentryShellGeneric sentryShell, String[] args,
+      String expectedErrorMsg) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
+  }
+
+  private void validateMissingParameterMsgsContains(SentryShellGeneric sentryShell, String[] args,
+      String ... expectedErrorMsgsContains) throws Exception {
+    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
+    boolean foundAllMessages = false;
+    Iterator<String> it = errorMsgs.iterator();
+    while (it.hasNext()) {
+      String errorMessage = it.next();
+      boolean missingExpected = false;
+      for (String expectedContains : expectedErrorMsgsContains) {
+        if (!errorMessage.contains(expectedContains)) {
+          missingExpected = true;
+          break;
+        }
+      }
+      if (!missingExpected) {
+        foundAllMessages = true;
+        break;
+      }
+    }
+    assertTrue(foundAllMessages);
+  }
+}


[6/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.

Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java
deleted file mode 100644
index 0f4bb62..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSolr.java
+++ /dev/null
@@ -1,534 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import com.google.common.io.Files;
-import com.google.common.collect.Sets;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.tools.SentryShellCommon;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestSentryShellSolr extends SentryGenericServiceIntegrationBase {
-  private File confDir;
-  private File confPath;
-  private static String TEST_ROLE_NAME_1 = "testRole1";
-  private static String TEST_ROLE_NAME_2 = "testRole2";
-  private String requestorName = "";
-  private String service = "service1";
-
-  @Before
-  public void prepareForTest() throws Exception {
-    confDir = Files.createTempDir();
-    confPath = new File(confDir, "sentry-site.xml");
-    if (confPath.createNewFile()) {
-      FileOutputStream to = new FileOutputStream(confPath);
-      conf.writeXml(to);
-      to.close();
-    }
-    requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
-    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
-    setLocalGroupMapping(requestorName, requestorUserGroupNames);
-    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
-    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
-    writePolicyFile();
-  }
-
-  @After
-  public void clearTestData() throws Exception {
-    FileUtils.deleteQuietly(confDir);
-  }
-
-  @Test
-  public void testCreateDropRole() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // test: create role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-        // test: create role with --create_role
-        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-
-        // validate the result, list roles with -lr
-        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // validate the result, list roles with --list_role
-        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // test: drop role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-        // test: drop role with --drop_role
-        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listAllRoles(requestorName, SOLR);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-      }
-    });
-  }
-
-  @Test
-  public void testAddDeleteRoleForGroup() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // Group names are case sensitive - mixed case names should work
-        String TEST_GROUP_1 = "testGroup1";
-        String TEST_GROUP_2 = "testGroup2";
-        String TEST_GROUP_3 = "testGroup3";
-
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
-        client.createRole(requestorName, TEST_ROLE_NAME_2, SOLR);
-        // test: add role to group with -arg
-        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-        // test: add role to multiple groups
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
-            "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-        // test: add role to group with --add_role_group
-        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
-            "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-
-        // validate the result list roles with -lr and -g
-        args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // list roles with --list_role and -g
-        args = new String[] { "--list_role", "-g", TEST_GROUP_2, "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        // List the groups and roles via listGroups
-        args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true);
-        assertEquals(3, groups.size());
-        assertTrue(groups.contains("testGroup3 = testrole1"));
-        assertTrue(groups.contains("testGroup2 = testrole1"));
-        assertTrue(groups.contains("testGroup1 = testrole2, testrole1"));
-
-        // test: delete role from group with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-        // test: delete role to multiple groups
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
-            "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-        // test: delete role from group with --delete_role_group
-        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
-            "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, SOLR);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, SOLR);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, SOLR);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2, SOLR);
-      }
-    });
-  }
-
-  @Test
-  public void testCaseSensitiveGroupName() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
-        // add role to a group (lower case)
-        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric.main(args);
-
-        // validate the roles when group name is same case as above
-        args = new String[] { "-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        // roles should be empty when group name is different case than above
-        args = new String[] { "-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames);
-      }
-      });
-    }
-
-  public static String grant(boolean shortOption) {
-    return shortOption ? "-gpr" : "--grant_privilege_role";
-  }
-
-  public static String revoke(boolean shortOption) {
-    return shortOption ? "-rpr" : "--revoke_privilege_role";
-  }
-
-  public static String list(boolean shortOption) {
-    return shortOption ? "-lp" : "--list_privilege";
-  }
-
-  private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
-        client.createRole(requestorName, TEST_ROLE_NAME_2, SOLR);
-
-        String [] privs = {
-          "Collection=*->action=*",
-          "Collection=collection2->action=update",
-          "Collection=collection3->action=query",
-        };
-        for (int i = 0; i < privs.length; ++i) {
-          // test: grant privilege to role
-          String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
-            privs[ i ],
-            "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-          SentryShellGeneric.main(args);
-        }
-
-        // test the list privilege
-        String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
-        assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
-        for (int i = 0; i < privs.length; ++i) {
-          assertTrue("Expected privilege: " + privs[ i ], privilegeStrs.contains(privs[ i ]));
-        }
-
-        for (int i = 0; i < privs.length; ++i) {
-          args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
-            privs[ i ], "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-          SentryShellGeneric.main(args);
-          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
-            TEST_ROLE_NAME_1, SOLR, service);
-          assertEquals("Incorrect number of privileges", privs.length - (i + 1), privileges.size());
-        }
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2, SOLR);
-      }
-    });
-  }
-
-
-  @Test
-  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
-    assertGrantRevokePrivilege(true);
-  }
-
-  @Test
-  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
-    assertGrantRevokePrivilege(false);
-  }
-
-
-  @Test
-  public void testNegativeCaseWithInvalidArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
-        // test: create duplicate role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for creating duplicate role");
-        } catch (SentryUserException e) {
-          // expected exception
-        }
-
-        // test: drop non-exist role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for dropping non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: add non-exist role to group with -arg
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for granting non-exist role to group");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: drop group from non-exist role with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for drop group from non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: grant privilege to role with the error privilege format
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=*",
-            "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for the error privilege format, invalid key value.");
-        } catch (IllegalArgumentException e) {
-          // excepted exception
-        }
-
-        // test: grant privilege to role with the error privilege hierarchy
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->table=tbl1->column=col2->action=insert", "-conf",
-            confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for the error privilege format, invalid key value.");
-        } catch (IllegalArgumentException e) {
-          // expected exception
-        }
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
-      }
-    });
-  }
-
-  @Test
-  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        String strOptionConf = "conf";
-        client.createRole(requestorName, TEST_ROLE_NAME_1, SOLR);
-        // test: the conf is required argument
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "solr" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
-
-        // test: -r is required when create role
-        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when drop role
-        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when add role to group
-        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when add role to group
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when delete role from group
-        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when delete role from group
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when grant privilege to role
-        args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when grant privilege to role
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: action is required in privilege
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "collection=collection1", "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-         try {
-          getShellResultWithOSRedirect(sentryShell, args, false);
-          fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-          assertEquals("Privilege is invalid: action required but not specified.", e.getMessage());
-        }
-
-        // test: -r is required when revoke privilege from role
-        args = new String[] { "-rpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when revoke privilege from role
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "solr" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: command option is required for shell
-        args = new String[] {"-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsgsContains(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
-                "-arg Add role to group",
-                "-cr Create role",
-                "-rpr Revoke privilege from role",
-                "-drg Delete role from group",
-                "-lr List role",
-                "-lp List privilege",
-                "-gpr Grant privilege to role",
-                "-dr Drop role");
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, SOLR);
-      }
-    });
-  }
-
-  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
-  private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
-      String[] args, boolean expectedExecuteResult) throws Exception {
-    PrintStream oldOut = System.out;
-    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
-    System.setOut(new PrintStream(outContent));
-    assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
-    Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n"));
-    System.setOut(oldOut);
-    return resultSet;
-  }
-
-  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
-    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
-      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
-          expectedRoleNames.length, roleNames.size());
-      Set<String> lowerCaseRoles = new HashSet<String>();
-      for (String role : roleNames) {
-        lowerCaseRoles.add(role.toLowerCase());
-      }
-
-      for (String expectedRole : expectedRoleNames) {
-        assertTrue("Expected role: " + expectedRole,
-            lowerCaseRoles.contains(expectedRole.toLowerCase()));
-      }
-    }
-  }
-
-  private void validateMissingParameterMsg(SentryShellGeneric sentryShell, String[] args,
-      String expectedErrorMsg) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
-  }
-
-  private void validateMissingParameterMsgsContains(SentryShellGeneric sentryShell, String[] args,
-      String ... expectedErrorMsgsContains) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    boolean foundAllMessages = false;
-    Iterator<String> it = errorMsgs.iterator();
-    while (it.hasNext()) {
-      String errorMessage = it.next();
-      boolean missingExpected = false;
-      for (String expectedContains : expectedErrorMsgsContains) {
-        if (!errorMessage.contains(expectedContains)) {
-          missingExpected = true;
-          break;
-        }
-      }
-      if (!missingExpected) {
-        foundAllMessages = true;
-        break;
-      }
-    }
-    assertTrue(foundAllMessages);
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSqoop.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSqoop.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSqoop.java
deleted file mode 100644
index cdba442..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestSentryShellSqoop.java
+++ /dev/null
@@ -1,532 +0,0 @@
-/**
- * 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.sentry.provider.db.generic.tools;
-
-import com.google.common.collect.Sets;
-import com.google.common.io.Files;
-import org.apache.commons.io.FileUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.common.AuthorizationComponent;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.tools.SentryShellCommon;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import static org.junit.Assert.*;
-
-public class TestSentryShellSqoop extends SentryGenericServiceIntegrationBase {
-  private File confDir;
-  private File confPath;
-  private static String TEST_ROLE_NAME_1 = "testRole1";
-  private static String TEST_ROLE_NAME_2 = "testRole2";
-  private String requestorName = "";
-  private String service = "sqoopServer1";
-
-  @Before
-  public void prepareForTest() throws Exception {
-    confDir = Files.createTempDir();
-    confPath = new File(confDir, "sentry-site.xml");
-    if (confPath.createNewFile()) {
-      FileOutputStream to = new FileOutputStream(confPath);
-      conf.writeXml(to);
-      to.close();
-    }
-    requestorName = clientUgi.getShortUserName();//.getProperty("user.name", "");
-    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
-    setLocalGroupMapping(requestorName, requestorUserGroupNames);
-    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
-    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
-    writePolicyFile();
-  }
-
-  @After
-  public void clearTestData() throws Exception {
-    FileUtils.deleteQuietly(confDir);
-  }
-
-  @Test
-  public void testCreateDropRole() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // test: create role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-        // test: create role with --create_role
-        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-
-        // validate the result, list roles with -lr
-        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // validate the result, list roles with --list_role
-        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // test: drop role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-        // test: drop role with --drop_role
-        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listAllRoles(requestorName, AuthorizationComponent.SQOOP);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-      }
-    });
-  }
-
-  @Test
-  public void testAddDeleteRoleForGroup() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // Group names are case sensitive - mixed case names should work
-        String TEST_GROUP_1 = "testGroup1";
-        String TEST_GROUP_2 = "testGroup2";
-        String TEST_GROUP_3 = "testGroup3";
-
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
-        client.createRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
-        // test: add role to group with -arg
-        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-        // test: add role to multiple groups
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
-            "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-        // test: add role to group with --add_role_group
-        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
-            "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-
-        // validate the result list roles with -lr and -g
-        args = new String[] { "-lr", "-g", TEST_GROUP_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // list roles with --list_role and -g
-        args = new String[] { "--list_role", "-g", TEST_GROUP_2, "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        args = new String[] { "--list_role", "-g", TEST_GROUP_3, "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        // List the groups and roles via listGroups
-        args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true);
-        assertEquals(3, groups.size());
-        assertTrue(groups.contains("testGroup3 = testrole1"));
-        assertTrue(groups.contains("testGroup2 = testrole1"));
-        assertTrue(groups.contains("testGroup1 = testrole2, testrole1"));
-
-        // test: delete role from group with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_1, "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-        // test: delete role to multiple groups
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", TEST_GROUP_2 + "," + TEST_GROUP_3,
-            "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-        // test: delete role from group with --delete_role_group
-        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", TEST_GROUP_1,
-            "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, TEST_GROUP_1, AuthorizationComponent.SQOOP);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_2, AuthorizationComponent.SQOOP);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, TEST_GROUP_3, AuthorizationComponent.SQOOP);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
-      }
-    });
-  }
-
-  @Test
-  public void testCaseSensitiveGroupName() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
-        // add role to a group (lower case)
-        String[] args = {"-arg", "-r", TEST_ROLE_NAME_1, "-g", "group1", "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop"};
-        SentryShellGeneric.main(args);
-
-        // validate the roles when group name is same case as above
-        args = new String[]{"-lr", "-g", "group1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop"};
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        // roles should be empty when group name is different case than above
-        args = new String[]{"-lr", "-g", "GROUP1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop"};
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames);
-      }
-    });
-  }
-
-  public static String grant(boolean shortOption) {
-    return shortOption ? "-gpr" : "--grant_privilege_role";
-  }
-
-  public static String revoke(boolean shortOption) {
-    return shortOption ? "-rpr" : "--revoke_privilege_role";
-  }
-
-  public static String list(boolean shortOption) {
-    return shortOption ? "-lp" : "--list_privilege";
-  }
-
-  private void assertGrantRevokePrivilege(final boolean shortOption) throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
-        client.createRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
-
-        String [] privs = {
-            "SERVER=sqoopserver1->CONNECTOR=c1->action=read",
-            "SERVER=sqoopserver1->JOB=j1->action=write",
-            "SERVER=sqoopserver1->LINK=l1->action=read",
-        };
-        for (int i = 0; i < privs.length; ++i) {
-          // test: grant privilege to role
-          String [] args = new String [] { grant(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
-            privs[ i ],
-            "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-          SentryShellGeneric.main(args);
-        }
-
-        // test the list privilege
-        String [] args = new String[] { list(shortOption), "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
-
-        assertEquals("Incorrect number of privileges", privs.length, privilegeStrs.size());
-        for (int i = 0; i < privs.length; ++i) {
-          assertTrue("Expected privilege: " + privs[i] + " in " + Arrays.toString(privilegeStrs.toArray()), privilegeStrs.contains(privs[i]));
-        }
-
-        for (int i = 0; i < privs.length; ++i) {
-          args = new String[] { revoke(shortOption), "-r", TEST_ROLE_NAME_1, "-p",
-            privs[ i ], "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-          SentryShellGeneric.main(args);
-          Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
-            TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP, service);
-          assertEquals("Incorrect number of privileges. Received privileges: " + Arrays.toString(privileges.toArray()), privs.length - (i + 1), privileges.size());
-        }
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2, AuthorizationComponent.SQOOP);
-      }
-    });
-  }
-
-
-  @Test
-  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
-    assertGrantRevokePrivilege(true);
-  }
-
-  @Test
-  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
-    assertGrantRevokePrivilege(false);
-  }
-
-  @Test
-  public void testNegativeCaseWithInvalidArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
-        // test: create duplicate role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for creating duplicate role");
-        } catch (SentryUserException e) {
-          // expected exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // test: drop non-exist role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for dropping non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // test: add non-exist role to group with -arg
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for granting non-exist role to group");
-        } catch (SentryUserException e) {
-          // excepted exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // test: drop group from non-exist role with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for drop group from non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // test: grant privilege to role with the error privilege format
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=all",
-            "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for the error privilege format, invalid key value.");
-        } catch (IllegalArgumentException e) {
-          // excepted exception
-        } catch (Exception e) {
-          fail ("Unexpected exception received. " + e);
-        }
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
-      }
-    });
-  }
-
-  @Test
-  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        String strOptionConf = "conf";
-        client.createRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
-        // test: the conf is required argument
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-t", "sqoop" };
-        SentryShellGeneric sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
-
-        // test: -r is required when create role
-        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when drop role
-        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when add role to group
-        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when add role to group
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when delete role from group
-        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when delete role from group
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when grant privilege to role
-        args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when grant privilege to role
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: action is required in privilege
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-p", "Server=sqoopServer1->Connector", "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-         try {
-          getShellResultWithOSRedirect(sentryShell, args, false);
-          fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-           // expected
-        } catch (Exception e) {
-           fail ("Unexpected exception received. " + e);
-         }
-
-        // test: -r is required when revoke privilege from role
-        args = new String[] { "-rpr", "-p", "Server=sqoopServer1->Connector->action=*", "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when revoke privilege from role
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: command option is required for shell
-        args = new String[] {"-conf", confPath.getAbsolutePath(), "-t", "sqoop" };
-        sentryShell = new SentryShellGeneric();
-        validateMissingParameterMsgsContains(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
-                "-arg Add role to group",
-                "-cr Create role",
-                "-rpr Revoke privilege from role",
-                "-drg Delete role from group",
-                "-lr List role",
-                "-lp List privilege",
-                "-gpr Grant privilege to role",
-                "-dr Drop role");
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1, AuthorizationComponent.SQOOP);
-      }
-    });
-  }
-
-  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
-  private Set<String> getShellResultWithOSRedirect(SentryShellGeneric sentryShell,
-      String[] args, boolean expectedExecuteResult) throws Exception {
-    PrintStream oldOut = System.out;
-    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
-    System.setOut(new PrintStream(outContent));
-    assertEquals(expectedExecuteResult, sentryShell.executeShell(args));
-    Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n"));
-    System.setOut(oldOut);
-    return resultSet;
-  }
-
-  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
-    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
-      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
-          expectedRoleNames.length, roleNames.size());
-      Set<String> lowerCaseRoles = new HashSet<String>();
-      for (String role : roleNames) {
-        lowerCaseRoles.add(role.toLowerCase());
-      }
-
-      for (String expectedRole : expectedRoleNames) {
-        assertTrue("Expected role: " + expectedRole,
-            lowerCaseRoles.contains(expectedRole.toLowerCase()));
-      }
-    }
-  }
-
-  private void validateMissingParameterMsg(SentryShellGeneric sentryShell, String[] args,
-      String expectedErrorMsg) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    assertTrue("Expected error message: " + expectedErrorMsg, errorMsgs.contains(expectedErrorMsg));
-  }
-
-  private void validateMissingParameterMsgsContains(SentryShellGeneric sentryShell, String[] args,
-      String ... expectedErrorMsgsContains) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    boolean foundAllMessages = false;
-    Iterator<String> it = errorMsgs.iterator();
-    while (it.hasNext()) {
-      String errorMessage = it.next();
-      boolean missingExpected = false;
-      for (String expectedContains : expectedErrorMsgsContains) {
-        if (!errorMessage.contains(expectedContains)) {
-          missingExpected = true;
-          break;
-        }
-      }
-      if (!missingExpected) {
-        foundAllMessages = true;
-        break;
-      }
-    }
-    assertTrue(foundAllMessages);
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentrySchemaTool.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentrySchemaTool.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentrySchemaTool.java
deleted file mode 100644
index 68abf27..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentrySchemaTool.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * 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.sentry.provider.db.tools;
-
-import java.io.File;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.service.persistent.SentryStoreSchemaInfo;
-import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.io.Files;
-
-public class TestSentrySchemaTool {
-  private Configuration sentryConf;
-  private SentrySchemaTool schemaTool;
-
-  private static final String OLDEST_INIT_VERSION = "1.4.0";
-
-  @Before
-  public void defaultSetup() throws Exception {
-    sentryConf = new Configuration();
-    File dbDir = new File(Files.createTempDir(), "sentry_policy_db");
-    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_URL,
-        "jdbc:derby:;databaseName=" + dbDir.getPath() + ";create=true");
-    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy");
-    schemaTool = new SentrySchemaTool("./src/main/resources", sentryConf,
-        "derby");
-  }
-
-  private void nonDefaultsetup() throws Exception {
-    sentryConf = new Configuration();
-    File dbDir = new File(Files.createTempDir(), "sentry_policy_db");
-    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_URL,
-        "jdbc:derby:;databaseName=" + dbDir.getPath() + ";create=true");
-    sentryConf.set(ServerConfig.SENTRY_STORE_JDBC_PASS, "dummy");
-    schemaTool = new SentrySchemaTool("./src/main/resources", sentryConf,
-        "derby");
-  }
-
-  @Test
-  public void testInitNonDefault() throws Exception {
-    nonDefaultsetup();
-    schemaTool.doInit();
-    schemaTool.verifySchemaVersion();
-  }
-
-  @Test
-  public void testInit() throws Exception {
-    schemaTool.doInit();
-    schemaTool.verifySchemaVersion();
-  }
-
-  @Test
-  public void testInitTo() throws Exception {
-    schemaTool.doInit(SentryStoreSchemaInfo.getSentryVersion());
-    schemaTool.verifySchemaVersion();
-  }
-
-  @Test(expected = SentryUserException.class)
-  public void testDryRun() throws Exception {
-    schemaTool.setDryRun(true);
-    schemaTool.doInit();
-    schemaTool.setDryRun(false);
-    // verification should fail since dryRun didn't create the actual schema
-    schemaTool.verifySchemaVersion();
-  }
-
-  @Test
-  public void testUpgrade() throws Exception {
-    schemaTool.doInit(OLDEST_INIT_VERSION);
-    schemaTool.doUpgrade();
-    schemaTool.verifySchemaVersion();
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentryShellHive.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentryShellHive.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentryShellHive.java
deleted file mode 100644
index de8f043..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/tools/TestSentryShellHive.java
+++ /dev/null
@@ -1,613 +0,0 @@
-/**
- * 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.sentry.provider.db.tools;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.service.thrift.TSentryRole;
-import org.apache.sentry.service.thrift.SentryServiceIntegrationBase;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.collect.Sets;
-import com.google.common.io.Files;
-
-public class TestSentryShellHive extends SentryServiceIntegrationBase {
-
-  private File confDir;
-  private File confPath;
-  private static String TEST_ROLE_NAME_1 = "testRole1";
-  private static String TEST_ROLE_NAME_2 = "testRole2";
-  private String requestorName = "";
-
-  @Before
-  public void prepareForTest() throws Exception {
-    confDir = Files.createTempDir();
-    confPath = new File(confDir, "sentry-site.xml");
-    if (confPath.createNewFile()) {
-      FileOutputStream to = new FileOutputStream(confPath);
-      conf.writeXml(to);
-      to.close();
-    }
-    requestorName = clientUgi.getShortUserName();
-    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
-    setLocalGroupMapping(requestorName, requestorUserGroupNames);
-    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
-    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
-    writePolicyFile();
-  }
-
-  @After
-  public void clearTestData() throws Exception {
-    FileUtils.deleteQuietly(confDir);
-  }
-
-  @Test
-  public void testCreateDropRole() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // test: create role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        // test: create role with --create_role
-        args = new String[] { "--create_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-
-        // validate the result, list roles with -lr
-        args = new String[] { "-lr", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive sentryShell = new SentryShellHive();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // validate the result, list roles with --list_role
-        args = new String[] { "--list_role", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-        // test: drop role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        // test: drop role with --drop_role
-        args = new String[] { "--drop_role", "-r", TEST_ROLE_NAME_2, "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listAllRoles(requestorName);
-        assertEquals("Incorrect number of roles", 0, roles.size());
-      }
-    });
-  }
-
-  @Test
-  public void testAddDeleteRoleForGroup() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1);
-        client.createRole(requestorName, TEST_ROLE_NAME_2);
-        // test: add role to group with -arg
-        String[] args = { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        // test: add role to multiple groups
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup2,testGroup3",
-            "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        // test: add role to group with --add_role_group
-        args = new String[] { "--add_role_group", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1",
-            "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-
-        // validate the result list roles with -lr and -g
-        args = new String[] { "-lr", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive sentryShell = new SentryShellHive();
-        Set<String> roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1, TEST_ROLE_NAME_2);
-
-
-        // list roles with --list_role and -g
-        args = new String[] { "--list_role", "-g", "testGroup2", "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        args = new String[] { "--list_role", "-g", "testGroup3", "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        roleNames = getShellResultWithOSRedirect(sentryShell, args, true);
-        validateRoleNames(roleNames, TEST_ROLE_NAME_1);
-
-        // List the groups and roles via listGroups
-        args = new String[] { "--list_group", "-conf", confPath.getAbsolutePath()};
-        sentryShell = new SentryShellHive();
-        Set<String> groups = getShellResultWithOSRedirect(sentryShell, args, true);
-        assertEquals(3, groups.size());
-        assertTrue(groups.contains("testGroup3 = testrole1"));
-        assertTrue(groups.contains("testGroup2 = testrole1"));
-        assertTrue(groups.contains("testGroup1 = testrole2, testrole1"));
-
-        // test: delete role from group with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        // test: delete role to multiple groups
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_1, "-g", "testGroup2,testGroup3",
-            "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        // test: delete role from group with --delete_role_group
-        args = new String[] { "--delete_role_group", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1",
-            "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-
-        // validate the result
-        Set<TSentryRole> roles = client.listRolesByGroupName(requestorName, "testGroup1");
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, "testGroup2");
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        roles = client.listRolesByGroupName(requestorName, "testGroup3");
-        assertEquals("Incorrect number of roles", 0, roles.size());
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2);
-      }
-    });
-  }
-
-  @Test
-  public void testGrantRevokePrivilegeWithShortOption() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1);
-        client.createRole(requestorName, TEST_ROLE_NAME_2);
-
-        // test: grant privilege to role with -gpr
-        String[] args = { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->action=*",
-            "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
-            "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-
-        // test the list privilege with -lp
-        args = new String[] { "-lp", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        SentryShellHive sentryShell = new SentryShellHive();
-        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
-        // validate the result for -lp
-        assertEquals("Incorrect number of privileges", 6, privilegeStrs.size());
-        assertTrue(privilegeStrs.contains("server=server1->action=*"));
-        assertTrue(privilegeStrs.contains("server=server1->db=db1->action=select"));
-        assertTrue(privilegeStrs.contains("server=server1->db=db1->table=tbl1->action=insert"));
-        assertTrue(privilegeStrs
-            .contains("server=server1->db=db1->table=tbl1->column=col1->action=insert"));
-        assertTrue(privilegeStrs
-            .contains("server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true"));
-        assertTrue(privilegeStrs.contains("server=server1->uri=hdfs://path/testuri->action=*"));
-
-        // test: revoke privilege from role with -rpr
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
-            TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 5, privileges.size());
-
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
-            "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 4, privileges.size());
-
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 3, privileges.size());
-
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 2, privileges.size());
-
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 1, privileges.size());
-
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-p", "server=server1->action=*",
-            "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 0, privileges.size());
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2);
-      }
-    });
-  }
-
-  @Test
-  public void testGrantRevokePrivilegeWithLongOption() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        // create the role for test
-        client.createRole(requestorName, TEST_ROLE_NAME_1);
-        client.createRole(requestorName, TEST_ROLE_NAME_2);
-
-        // test: grant privilege to role with -gpr
-        String[] args = { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->action=*", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
-            "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        args = new String[] { "--grant_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-
-        // test the list privilege with -lp
-        args = new String[] { "--list_privilege", "-r", TEST_ROLE_NAME_1, "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive sentryShell = new SentryShellHive();
-        Set<String> privilegeStrs = getShellResultWithOSRedirect(sentryShell, args, true);
-        // validate the result for -lp
-        assertEquals("Incorrect number of privileges", 6, privilegeStrs.size());
-        assertTrue(privilegeStrs.contains("server=server1->action=*"));
-        assertTrue(privilegeStrs.contains("server=server1->db=db1->action=select"));
-        assertTrue(privilegeStrs.contains("server=server1->db=db1->table=tbl1->action=insert"));
-        assertTrue(privilegeStrs
-            .contains("server=server1->db=db1->table=tbl1->column=col1->action=insert"));
-        assertTrue(privilegeStrs
-            .contains("server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true"));
-        assertTrue(privilegeStrs.contains("server=server1->uri=hdfs://path/testuri->action=*"));
-
-        // test: revoke privilege from role with -rpr
-        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->column=col1->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(requestorName,
-            TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 5, privileges.size());
-
-        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->column=col2->action=insert->grantoption=true",
-            "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 4, privileges.size());
-
-        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->uri=hdfs://path/testuri->action=*", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 3, privileges.size());
-
-        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->table=tbl1->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 2, privileges.size());
-
-        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->db=db1->action=select", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 1, privileges.size());
-
-        args = new String[] { "--revoke_privilege_role", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->action=*", "-conf", confPath.getAbsolutePath() };
-        SentryShellHive.main(args);
-        privileges = client.listAllPrivilegesByRoleName(requestorName, TEST_ROLE_NAME_1);
-        assertEquals("Incorrect number of privileges", 0, privileges.size());
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1);
-        client.dropRole(requestorName, TEST_ROLE_NAME_2);
-      }
-    });
-  }
-
-  @Test
-  public void testNegativeCaseWithInvalidArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        client.createRole(requestorName, TEST_ROLE_NAME_1);
-        // test: create duplicate role with -cr
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        SentryShellHive sentryShell = new SentryShellHive();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for creating duplicate role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: drop non-exist role with -dr
-        args = new String[] { "-dr", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for dropping non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: add non-exist role to group with -arg
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for granting non-exist role to group");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: drop group from non-exist role with -drg
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-g", "testGroup1", "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for drop group from non-exist role");
-        } catch (SentryUserException e) {
-          // excepted exception
-        }
-
-        // test: grant privilege to role with the error privilege format
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p", "serverserver1->action=*",
-            "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for the error privilege format, invalid key value.");
-        } catch (IllegalArgumentException e) {
-          // excepted exception
-        }
-
-        // test: grant privilege to role with the error privilege hierarchy
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-p",
-            "server=server1->table=tbl1->column=col2->action=insert", "-conf",
-            confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        try {
-          sentryShell.executeShell(args);
-          fail("Exception should be thrown for the error privilege format, invalid key value.");
-        } catch (IllegalArgumentException e) {
-          // excepted exception
-        }
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1);
-      }
-    });
-  }
-
-  @Test
-  public void testNegativeCaseWithoutRequiredArgument() throws Exception {
-    runTestAsSubject(new TestOperation() {
-      @Override
-      public void runTestAsSubject() throws Exception {
-        String strOptionConf = "conf";
-        client.createRole(requestorName, TEST_ROLE_NAME_1);
-        // test: the conf is required argument
-        String[] args = { "-cr", "-r", TEST_ROLE_NAME_1 };
-        SentryShellHive sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + strOptionConf);
-
-        // test: -r is required when create role
-        args = new String[] { "-cr", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when drop role
-        args = new String[] { "-dr", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -r is required when add role to group
-        args = new String[] { "-arg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when add role to group
-        args = new String[] { "-arg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when delete role from group
-        args = new String[] { "-drg", "-g", "testGroup1", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -g is required when delete role from group
-        args = new String[] { "-drg", "-r", TEST_ROLE_NAME_2, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_GROUP_NAME);
-
-        // test: -r is required when grant privilege to role
-        args = new String[] { "-gpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when grant privilege to role
-        args = new String[] { "-gpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: -r is required when revoke privilege from role
-        args = new String[] { "-rpr", "-p", "server=server1", "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_ROLE_NAME);
-
-        // test: -p is required when revoke privilege from role
-        args = new String[] { "-rpr", "-r", TEST_ROLE_NAME_1, "-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsg(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + SentryShellCommon.OPTION_DESC_PRIVILEGE);
-
-        // test: command option is required for shell
-        args = new String[] {"-conf", confPath.getAbsolutePath() };
-        sentryShell = new SentryShellHive();
-        validateMissingParameterMsgsContains(sentryShell, args,
-                SentryShellCommon.PREFIX_MESSAGE_MISSING_OPTION + "[",
-                "-arg Add role to group",
-                "-cr Create role",
-                "-rpr Revoke privilege from role",
-                "-drg Delete role from group",
-                "-lr List role",
-                "-lp List privilege",
-                "-gpr Grant privilege to role",
-                "-dr Drop role");
-
-        // clear the test data
-        client.dropRole(requestorName, TEST_ROLE_NAME_1);
-      }
-    });
-  }
-
-  // redirect the System.out to ByteArrayOutputStream, then execute the command and parse the result.
-  private Set<String> getShellResultWithOSRedirect(SentryShellHive sentryShell,
-      String[] args, boolean exceptedExecuteResult) throws Exception {
-    PrintStream oldOut = System.out;
-    ByteArrayOutputStream outContent = new ByteArrayOutputStream();
-    System.setOut(new PrintStream(outContent));
-    assertEquals(exceptedExecuteResult, sentryShell.executeShell(args));
-    Set<String> resultSet = Sets.newHashSet(outContent.toString().split("\n"));
-    System.setOut(oldOut);
-    return resultSet;
-  }
-
-  private void validateRoleNames(Set<String> roleNames, String ... expectedRoleNames) {
-    if (expectedRoleNames != null && expectedRoleNames.length > 0) {
-      assertEquals("Found: " + roleNames.size() + " roles, expected: " + expectedRoleNames.length,
-          expectedRoleNames.length, roleNames.size());
-      Set<String> lowerCaseRoles = new HashSet<String>();
-      for (String role : roleNames) {
-        lowerCaseRoles.add(role.toLowerCase());
-      }
-
-      for (String expectedRole : expectedRoleNames) {
-        assertTrue("Expected role: " + expectedRole,
-            lowerCaseRoles.contains(expectedRole.toLowerCase()));
-      }
-    }
-  }
-
-  private void validateMissingParameterMsg(SentryShellHive sentryShell, String[] args,
-      String exceptedErrorMsg) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    assertTrue(errorMsgs.contains(exceptedErrorMsg));
-  }
-
-  private void validateMissingParameterMsgsContains(SentryShellHive sentryShell, String[] args,
-      String ... expectedErrorMsgsContains) throws Exception {
-    Set<String> errorMsgs = getShellResultWithOSRedirect(sentryShell, args, false);
-    boolean foundAllMessages = false;
-    Iterator<String> it = errorMsgs.iterator();
-    while (it.hasNext()) {
-      String errorMessage = it.next();
-      boolean missingExpected = false;
-      for (String expectedContains : expectedErrorMsgsContains) {
-        if (!errorMessage.contains(expectedContains)) {
-          missingExpected = true;
-          break;
-        }
-      }
-      if (!missingExpected) {
-        foundAllMessages = true;
-        break;
-      }
-    }
-    assertTrue(foundAllMessages);
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/indexer_case.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/indexer_case.ini b/sentry-provider/sentry-provider-db/src/test/resources/indexer_case.ini
deleted file mode 100644
index f1afe1f..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/indexer_case.ini
+++ /dev/null
@@ -1,26 +0,0 @@
-# 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.
-
-[groups]
-groupa = RoLe1
-groupb = rOlE1
-groupc = ROLE2
-
-[roles]
-RoLe1 = indexer=*
-rOlE1 = indexer=*
-ROLE2 = indexer=*


[8/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.

Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaHelper.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaHelper.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaHelper.java
deleted file mode 100644
index cf1c725..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaHelper.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/**
- * 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.sentry.provider.db.tools;
-
-import java.util.IllegalFormatException;
-
-public final class SentrySchemaHelper {
-  public static final String DB_DERBY = "derby";
-  public static final String DB_MYSQL = "mysql";
-  public static final String DB_POSTGRACE = "postgres";
-  public static final String DB_ORACLE = "oracle";
-  public static final String DB_DB2 = "db2";
-
-  public interface NestedScriptParser {
-
-    public enum CommandType {
-      PARTIAL_STATEMENT,
-      TERMINATED_STATEMENT,
-      COMMENT
-    }
-
-    String DEFAUTL_DELIMITER = ";";
-    /***
-     * Find the type of given command
-     * @param dbCommand
-     * @return
-     */
-    boolean isPartialCommand(String dbCommand) throws IllegalArgumentException;
-
-    /** Parse the DB specific nesting format and extract the inner script name if any
-     * @param dbCommand command from parent script
-     * @return
-     * @throws IllegalFormatException
-     */
-    String getScriptName(String dbCommand) throws IllegalArgumentException;
-
-    /***
-     * Find if the given command is a nested script execution
-     * @param dbCommand
-     * @return
-     */
-    boolean isNestedScript(String dbCommand);
-
-    /***
-     * Find if the given command is should be passed to DB
-     * @param dbCommand
-     * @return
-     */
-    boolean isNonExecCommand(String dbCommand);
-
-    /***
-     * Get the SQL statement delimiter
-     * @return
-     */
-    String getDelimiter();
-
-    /***
-     * Clear any client specific tags
-     * @return
-     */
-    String cleanseCommand(String dbCommand);
-
-    /***
-     * Does the DB required table/column names quoted
-     * @return
-     */
-    boolean needsQuotedIdentifier();
-
-    /***
-     * Set DB specific options if any
-     * @param dbOps
-     */
-    void setDbOpts(String dbOps);
-  }
-
-
-  /***
-   * Base implemenation of NestedScriptParser
-   * abstractCommandParser.
-   *
-   */
-  private static abstract class AbstractCommandParser implements NestedScriptParser {
-    private String dbOpts = null;
-
-    @Override
-    public boolean isPartialCommand(String dbCommand) throws IllegalArgumentException{
-      if (dbCommand == null || dbCommand.isEmpty()) {
-        throw new IllegalArgumentException("invalid command line " + dbCommand);
-      }
-      String trimmedDbCommand = dbCommand.trim();
-      return !(trimmedDbCommand.endsWith(getDelimiter()) || isNonExecCommand(trimmedDbCommand));
-    }
-
-    @Override
-    public boolean isNonExecCommand(String dbCommand) {
-      return dbCommand.startsWith("--") || dbCommand.startsWith("#");
-    }
-
-    @Override
-    public String getDelimiter() {
-      return DEFAUTL_DELIMITER;
-    }
-
-    @Override
-    public String cleanseCommand(String dbCommand) {
-      // strip off the delimiter
-      if (dbCommand.endsWith(getDelimiter())) {
-        dbCommand = dbCommand.substring(0,
-            dbCommand.length() - getDelimiter().length());
-      }
-      return dbCommand;
-    }
-
-    @Override
-    public boolean needsQuotedIdentifier() {
-      return false;
-    }
-
-    @Override
-    public void setDbOpts(String dbOpts) {
-      this.dbOpts = dbOpts;
-    }
-
-    protected String getDbOpts() {
-      return dbOpts;
-    }
-  }
-
-
-  // Derby commandline parser
-  public static class DerbyCommandParser extends AbstractCommandParser {
-    private static final String DERBY_NESTING_TOKEN = "RUN";
-
-    @Override
-    public String getScriptName(String dbCommand) throws IllegalArgumentException {
-
-      if (!isNestedScript(dbCommand)) {
-        throw new IllegalArgumentException("Not a script format " + dbCommand);
-      }
-      String[] tokens = dbCommand.split(" ");
-      if (tokens.length != 2) {
-        throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
-      }
-      return tokens[1].replace(";", "").replaceAll("'", "");
-    }
-
-    @Override
-    public boolean isNestedScript(String dbCommand) {
-      // Derby script format is RUN '<file>'
-     return dbCommand.startsWith(DERBY_NESTING_TOKEN);
-    }
-  }
-
-
-  // MySQL parser
-  public static class MySqlCommandParser extends AbstractCommandParser {
-    private static final String MYSQL_NESTING_TOKEN = "SOURCE";
-    private static final String DELIMITER_TOKEN = "DELIMITER";
-    private String delimiter = DEFAUTL_DELIMITER;
-
-    @Override
-    public boolean isPartialCommand(String dbCommand) throws IllegalArgumentException{
-      boolean isPartial = super.isPartialCommand(dbCommand);
-      // if this is a delimiter directive, reset our delimiter
-      if (dbCommand.startsWith(DELIMITER_TOKEN)) {
-        String[] tokens = dbCommand.split(" ");
-        if (tokens.length != 2) {
-          throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
-        }
-        delimiter = tokens[1];
-      }
-      return isPartial;
-    }
-
-    @Override
-    public String getScriptName(String dbCommand) throws IllegalArgumentException {
-      String[] tokens = dbCommand.split(" ");
-      if (tokens.length != 2) {
-        throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
-      }
-      // remove ending ';'
-      return tokens[1].replace(";", "");
-    }
-
-    @Override
-    public boolean isNestedScript(String dbCommand) {
-      return dbCommand.startsWith(MYSQL_NESTING_TOKEN);
-    }
-
-    @Override
-    public String getDelimiter() {
-      return delimiter;
-    }
-
-    @Override
-    public boolean isNonExecCommand(String dbCommand) {
-      return super.isNonExecCommand(dbCommand) ||
-          dbCommand.startsWith("/*") && dbCommand.endsWith("*/") ||
-          dbCommand.startsWith(DELIMITER_TOKEN);
-    }
-
-    @Override
-    public String cleanseCommand(String dbCommand) {
-      return super.cleanseCommand(dbCommand).replaceAll("/\\*.*?\\*/[^;]", "");
-    }
-
-  }
-
-  // Postgres specific parser
-  public static class PostgresCommandParser extends AbstractCommandParser {
-    public static final String POSTGRES_STRING_COMMAND_FILTER = "SET standard_conforming_strings";
-    public static final String POSTGRES_STRING_CLIENT_ENCODING = "SET client_encoding";
-    public static final String POSTGRES_SKIP_STANDARD_STRING = "postgres.filter.81";
-    private static final String POSTGRES_NESTING_TOKEN = "\\i";
-
-    @Override
-    public String getScriptName(String dbCommand) throws IllegalArgumentException {
-      String[] tokens = dbCommand.split(" ");
-      if (tokens.length != 2) {
-        throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
-      }
-      // remove ending ';'
-      return tokens[1].replace(";", "");
-    }
-
-    @Override
-    public boolean isNestedScript(String dbCommand) {
-      return dbCommand.startsWith(POSTGRES_NESTING_TOKEN);
-    }
-
-    @Override
-    public boolean needsQuotedIdentifier() {
-      return true;
-    }
-
-    @Override
-    public boolean isNonExecCommand(String dbCommand) {
-      // Skip "standard_conforming_strings" command which is not supported in older postgres
-      if (POSTGRES_SKIP_STANDARD_STRING.equalsIgnoreCase(getDbOpts()) 
-        && (dbCommand.startsWith(POSTGRES_STRING_COMMAND_FILTER) || dbCommand.startsWith(POSTGRES_STRING_CLIENT_ENCODING))) {
-        return true;
-      }
-      return super.isNonExecCommand(dbCommand);
-    }
-  }
-
-  //Oracle specific parser
-  public static class OracleCommandParser extends AbstractCommandParser {
-    private static final String ORACLE_NESTING_TOKEN = "@";
-    @Override
-    public String getScriptName(String dbCommand) throws IllegalArgumentException {
-      if (!isNestedScript(dbCommand)) {
-        throw new IllegalArgumentException("Not a nested script format " + dbCommand);
-      }
-      // remove ending ';' and starting '@'
-      return dbCommand.replace(";", "").replace(ORACLE_NESTING_TOKEN, "");
-    }
-
-    @Override
-    public boolean isNestedScript(String dbCommand) {
-      return dbCommand.startsWith(ORACLE_NESTING_TOKEN);
-    }
-  }
-
-  // DB2 commandline parser
-  public static class DB2CommandParser extends AbstractCommandParser {
-
-    @Override
-    public String getScriptName(String dbCommand) throws IllegalArgumentException {
-        //DB2 does not support nesting script
-        throw new IllegalArgumentException("DB2 does not support nesting script " + dbCommand);
-    }
-
-    @Override
-    public boolean isNestedScript(String dbCommand) {
-        //DB2 does not support nesting script
-     return false;
-    }
-  }
-
-  public static NestedScriptParser getDbCommandParser(String dbName) {
-    if (dbName.equalsIgnoreCase(DB_DERBY)) {
-      return new DerbyCommandParser();
-    } else if (dbName.equalsIgnoreCase(DB_MYSQL)) {
-      return new MySqlCommandParser();
-    } else if (dbName.equalsIgnoreCase(DB_POSTGRACE)) {
-      return new PostgresCommandParser();
-    } else if (dbName.equalsIgnoreCase(DB_ORACLE)) {
-        return new OracleCommandParser();
-    } else if (dbName.equalsIgnoreCase(DB_DB2)) {
-      return new DB2CommandParser();
-    } else {
-      throw new IllegalArgumentException("Unknown dbType " + dbName);
-    }
-  }
-  
-  private SentrySchemaHelper() {
-    // Make constructor private to avoid instantiation
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java
deleted file mode 100644
index d75e24b..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentrySchemaTool.java
+++ /dev/null
@@ -1,595 +0,0 @@
-/**
- * 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.sentry.provider.db.tools;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.net.MalformedURLException;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.IllegalFormatException;
-import java.util.List;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.CommandLineParser;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.OptionGroup;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.io.output.NullOutputStream;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hive.beeline.BeeLine;
-import org.apache.sentry.Command;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.core.common.exception.SentrySiteConfigurationException;
-import org.apache.sentry.provider.db.service.persistent.SentryStoreSchemaInfo;
-import org.apache.sentry.provider.db.tools.SentrySchemaHelper.NestedScriptParser;
-import org.apache.sentry.service.thrift.SentryService;
-import org.apache.sentry.service.thrift.ServiceConstants;
-
-public class SentrySchemaTool {
-  private static final String SENTRY_SCRIP_DIR = File.separatorChar + "scripts"
-      + File.separatorChar + "sentrystore" + File.separatorChar + "upgrade";
-  private String userName = null;
-  private String passWord = null;
-  private String connectionURL = null;
-  private String driver = null;
-  private boolean dryRun = false;
-  private String dbOpts = null;
-  private boolean verbose = false;
-  private final Configuration sentryConf;
-  private final String dbType;
-  private final SentryStoreSchemaInfo sentryStoreSchemaInfo;
-
-  public SentrySchemaTool(Configuration sentryConf, String dbType)
-      throws SentryUserException, IOException {
-    this(System.getenv("SENTRY_HOME") + SENTRY_SCRIP_DIR, sentryConf, dbType);
-  }
-
-  public SentrySchemaTool(String sentryScripPath, Configuration sentryConf,
-      String dbType) throws SentryUserException, IOException {
-    if (sentryScripPath == null || sentryScripPath.isEmpty()) {
-      throw new SentryUserException("No Sentry script dir provided");
-    }
-    this.sentryConf = sentryConf;
-    this.dbType = dbType;
-    this.sentryStoreSchemaInfo = new SentryStoreSchemaInfo(sentryScripPath,
-        dbType);
-    userName = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER,
-        ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_USER_DEFAULT);
-    //Password will be read from Credential provider specified using property
-    // CREDENTIAL_PROVIDER_PATH("hadoop.security.credential.provider.path" in sentry-site.xml
-    // it falls back to reading directly from sentry-site.xml
-    char[] passTmp = sentryConf.getPassword(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
-    if(passTmp != null) {
-      passWord = new String(passTmp);
-    } else {
-      throw new SentrySiteConfigurationException("Error reading " + ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_PASS);
-    }
-
-    try {
-      connectionURL = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_URL);
-      if(dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)) {
-        driver = sentryConf.get(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER,
-            ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER_DEFAULT);
-      } else {
-        driver = getValidConfVar(ServiceConstants.ServerConfig.SENTRY_STORE_JDBC_DRIVER);
-      }
-      // load required JDBC driver
-      Class.forName(driver);
-    } catch (IOException e) {
-      throw new SentryUserException("Missing property: " + e.getMessage());
-    } catch (ClassNotFoundException e) {
-      throw new SentryUserException("Failed to load driver", e);
-    }
-  }
-
-  public Configuration getConfiguration() {
-    return sentryConf;
-  }
-
-  public void setUserName(String userName) {
-    this.userName = userName;
-  }
-
-  public void setPassWord(String passWord) {
-    this.passWord = passWord;
-  }
-
-  public void setDryRun(boolean dryRun) {
-    this.dryRun = dryRun;
-  }
-
-  public void setVerbose(boolean verbose) {
-    this.verbose = verbose;
-  }
-
-  public String getDbOpts() {
-    return dbOpts;
-  }
-
-  public void setDbOpts(String dbOpts) {
-    this.dbOpts = dbOpts;
-  }
-
-  private static void printAndExit(Options cmdLineOptions) {
-    HelpFormatter formatter = new HelpFormatter();
-    formatter.printHelp("schemaTool", cmdLineOptions);
-    System.exit(1);
-  }
-
-  /***
-   * Print Hive version and schema version
-   * @throws SentryUserException
-   */
-  public void showInfo() throws SentryUserException {
-    Connection sentryStoreConn = getConnectionToMetastore(true);
-    System.out.println("Sentry distribution version:\t "
-        + SentryStoreSchemaInfo.getSentryVersion());
-    System.out.println("SentryStore schema version:\t "
-        + getMetaStoreSchemaVersion(sentryStoreConn));
-  }
-
-  // read schema version from sentry store
-  private String getMetaStoreSchemaVersion(Connection sentryStoreConn)
-      throws SentryUserException {
-    String versionQuery;
-    if (SentrySchemaHelper.getDbCommandParser(dbType).needsQuotedIdentifier()) {
-      versionQuery = "select t.\"SCHEMA_VERSION\" from \"SENTRY_VERSION\" t";
-    } else {
-      versionQuery = "select t.SCHEMA_VERSION from SENTRY_VERSION t";
-    }
-    try (Statement stmt = sentryStoreConn.createStatement();
-      ResultSet res = stmt.executeQuery(versionQuery)) {
-      if (!res.next()) {
-        throw new SentryUserException("Didn't find version data in sentry store");
-      }
-      String currentSchemaVersion = res.getString(1);
-      sentryStoreConn.close();
-      return currentSchemaVersion;
-    } catch (SQLException e) {
-      throw new SentryUserException("Failed to get schema version.", e);
-    }
-  }
-
-  // test the connection sentry store using the config property
-  private void testConnectionToMetastore() throws SentryUserException {
-    try (Connection conn = getConnectionToMetastore(true)) {
-      conn.close();
-    } catch (SQLException e) {
-      throw new SentryUserException("Failed to close sentry store connection", e);
-    }
-  }
-
-  /***
-   * get JDBC connection to sentry store db
-   *
-   * @param printInfo print connection parameters
-   * @return
-   * @throws SentryUserException
-   */
-  private Connection getConnectionToMetastore(boolean printInfo)
-      throws SentryUserException {
-    if (printInfo) {
-      System.out.println("Sentry store connection URL:\t " + connectionURL);
-      System.out.println("Sentry store Connection Driver :\t " + driver);
-      System.out.println("Sentry store connection User:\t " + userName);
-    }
-    if (userName == null || userName.isEmpty()) {
-      throw new SentryUserException("UserName empty ");
-    }
-    try {
-      // Connect using the JDBC URL and user/pass from conf
-      return DriverManager.getConnection(connectionURL, userName, passWord);
-    } catch (SQLException e) {
-      throw new SentryUserException("Failed to make connection to Sentry store.", e);
-    }
-  }
-
-  /**
-   * check if the current schema version in sentry store matches the Hive version
-   * @throws SentryUserException
-   */
-  public void verifySchemaVersion() throws SentryUserException {
-    // don't check version if its a dry run
-    if (dryRun) {
-      return;
-    }
-    String newSchemaVersion =
-        getMetaStoreSchemaVersion(getConnectionToMetastore(false));
-    // verify that the new version is added to schema
-    if (!sentryStoreSchemaInfo.getSentrySchemaVersion().equalsIgnoreCase(
-        newSchemaVersion)) {
-      throw new SentryUserException("Found unexpected schema version "
-          + newSchemaVersion);
-    }
-  }
-
-  /**
-   * Perform sentry store schema upgrade. extract the current schema version from sentry store
-   * @throws SentryUserException
-   */
-  public void doUpgrade() throws SentryUserException {
-    String fromVersion = getMetaStoreSchemaVersion(getConnectionToMetastore(false));
-    if (fromVersion == null || fromVersion.isEmpty()) {
-      throw new SentryUserException(
-          "Schema version not stored in the sentry store. "
-              +
-          "Metastore schema is too old or corrupt. Try specifying the version manually");
-    }
-    doUpgrade(fromVersion);
-  }
-
-  /**
-   * Perform sentry store schema upgrade
-   *
-   * @param fromSchemaVer
-   *          Existing version of the sentry store. If null, then read from the sentry store
-   * @throws SentryUserException
-   */
-  public void doUpgrade(String fromSchemaVer) throws SentryUserException {
-    if (sentryStoreSchemaInfo.getSentrySchemaVersion().equals(fromSchemaVer)) {
-      System.out.println("No schema upgrade required from version " + fromSchemaVer);
-      return;
-    }
-    // Find the list of scripts to execute for this upgrade
-    List<String> upgradeScripts =
-        sentryStoreSchemaInfo.getUpgradeScripts(fromSchemaVer);
-    testConnectionToMetastore();
-    System.out.println("Starting upgrade sentry store schema from version " +
- fromSchemaVer + " to "
-        + sentryStoreSchemaInfo.getSentrySchemaVersion());
-    String scriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
-    try {
-      for (String scriptFile : upgradeScripts) {
-        System.out.println("Upgrade script " + scriptFile);
-        if (!dryRun) {
-          runBeeLine(scriptDir, scriptFile);
-          System.out.println("Completed " + scriptFile);
-        }
-      }
-    } catch (IOException eIO) {
-      throw new SentryUserException(
-          "Upgrade FAILED! Metastore state would be inconsistent !!", eIO);
-    }
-
-    // Revalidated the new version after upgrade
-    verifySchemaVersion();
-  }
-
-  /**
-   * Initialize the sentry store schema to current version
-   *
-   * @throws SentryUserException
-   */
-  public void doInit() throws SentryUserException {
-    doInit(sentryStoreSchemaInfo.getSentrySchemaVersion());
-
-    // Revalidated the new version after upgrade
-    verifySchemaVersion();
-  }
-
-  /**
-   * Initialize the sentry store schema
-   *
-   * @param toVersion
-   *          If null then current hive version is used
-   * @throws SentryUserException
-   */
-  public void doInit(String toVersion) throws SentryUserException {
-    testConnectionToMetastore();
-    System.out.println("Starting sentry store schema initialization to " + toVersion);
-
-    String initScriptDir = sentryStoreSchemaInfo.getSentryStoreScriptDir();
-    String initScriptFile = sentryStoreSchemaInfo.generateInitFileName(toVersion);
-
-    try {
-      System.out.println("Initialization script " + initScriptFile);
-      if (!dryRun) {
-        runBeeLine(initScriptDir, initScriptFile);
-        System.out.println("Initialization script completed");
-      }
-    } catch (IOException e) {
-      throw new SentryUserException("Schema initialization FAILED!"
-          + " Metastore state would be inconsistent !!", e);
-    }
-  }
-
-  // Flatten the nested upgrade script into a buffer
-  public static String buildCommand(NestedScriptParser dbCommandParser,
-        String scriptDir, String scriptFile) throws IllegalFormatException, IOException {
-
-    BufferedReader bfReader =
-        new BufferedReader(new FileReader(scriptDir + File.separatorChar + scriptFile));
-    String currLine;
-    StringBuilder sb = new StringBuilder();
-    String currentCommand = null;
-    while ((currLine = bfReader.readLine()) != null) {
-      currLine = currLine.trim();
-      if (currLine.isEmpty()) {
-        continue; // skip empty lines
-      }
-
-      if (currentCommand == null) {
-        currentCommand = currLine;
-      } else {
-        currentCommand = currentCommand + " " + currLine;
-      }
-      if (dbCommandParser.isPartialCommand(currLine)) {
-        // if its a partial line, continue collecting the pieces
-        continue;
-      }
-
-      // if this is a valid executable command then add it to the buffer
-      if (!dbCommandParser.isNonExecCommand(currentCommand)) {
-        currentCommand = dbCommandParser.cleanseCommand(currentCommand);
-
-        if (dbCommandParser.isNestedScript(currentCommand)) {
-          // if this is a nested sql script then flatten it
-          String currScript = dbCommandParser.getScriptName(currentCommand);
-          sb.append(buildCommand(dbCommandParser, scriptDir, currScript));
-        } else {
-          // Now we have a complete statement, process it
-          // write the line to buffer
-          sb.append(currentCommand);
-          sb.append(System.getProperty("line.separator"));
-        }
-      }
-      currentCommand = null;
-    }
-    bfReader.close();
-    return sb.toString();
-  }
-
-  // run beeline on the given sentry store scrip, flatten the nested scripts into single file
-  private void runBeeLine(String scriptDir, String scriptFile) throws IOException {
-    NestedScriptParser dbCommandParser =
-        SentrySchemaHelper.getDbCommandParser(dbType);
-    dbCommandParser.setDbOpts(getDbOpts());
-    // expand the nested script
-    String sqlCommands = buildCommand(dbCommandParser, scriptDir, scriptFile);
-    File tmpFile = File.createTempFile("schematool", ".sql");
-    tmpFile.deleteOnExit();
-
-    // write out the buffer into a file. Add beeline commands for autocommit and close
-    try (FileWriter fstream = new FileWriter(tmpFile.getPath());
-      BufferedWriter out = new BufferedWriter(fstream)) {
-
-      out.write("!set Silent " + verbose + System.getProperty("line.separator"));
-      out.write("!autocommit on" + System.getProperty("line.separator"));
-      out.write("!set Isolation TRANSACTION_READ_COMMITTED"
-          + System.getProperty("line.separator"));
-      out.write("!set AllowMultiLineCommand false"
-          + System.getProperty("line.separator"));
-      out.write(sqlCommands);
-      out.write("!closeall" + System.getProperty("line.separator"));
-      out.close();
-    }
-    runBeeLine(tmpFile.getPath());
-  }
-
-  // Generate the beeline args per hive conf and execute the given script
-  public void runBeeLine(String sqlScriptFile) throws IOException {
-    List<String> argList = new ArrayList<String>();
-    argList.add("-u");
-    argList.add(connectionURL);
-    argList.add("-d");
-    argList
-        .add(driver);
-    argList.add("-n");
-    argList.add(userName);
-    argList.add("-p");
-    argList.add(passWord);
-    argList.add("-f");
-    argList.add(sqlScriptFile);
-
-    BeeLine beeLine = new BeeLine();
-    if (!verbose) {
-      beeLine.setOutputStream(new PrintStream(new NullOutputStream()));
-      // beeLine.getOpts().setSilent(true);
-    }
-    // beeLine.getOpts().setAllowMultiLineCommand(false);
-    // beeLine.getOpts().setIsolation("TRANSACTION_READ_COMMITTED");
-    int status = beeLine.begin(argList.toArray(new String[0]), null);
-    if (status != 0) {
-      throw new IOException("Schema script failed, errorcode " + status);
-    }
-  }
-
-  private String getValidConfVar(String confVar) throws IOException {
-    String confVarKey = confVar;
-    String confVarValue = sentryConf.get(confVarKey);
-    if (confVarValue == null || confVarValue.isEmpty()) {
-      throw new IOException("Empty " + confVar);
-    }
-    return confVarValue;
-  }
-
-  // Create the required command line options
-  @SuppressWarnings("static-access")
-  private static void initOptions(Options cmdLineOptions) {
-    Option help = new Option("help", "print this message");
-    Option upgradeOpt = new Option("upgradeSchema", "Schema upgrade");
-    Option upgradeFromOpt = OptionBuilder.withArgName("upgradeFrom").hasArg().
-                withDescription("Schema upgrade from a version").
-                create("upgradeSchemaFrom");
-    Option initOpt = new Option("initSchema", "Schema initialization");
-    Option initToOpt = OptionBuilder.withArgName("initTo").hasArg().
-                withDescription("Schema initialization to a version").
-                create("initSchemaTo");
-    Option infoOpt = new Option("info", "Show config and schema details");
-
-    OptionGroup optGroup = new OptionGroup();
-    optGroup.addOption(upgradeOpt).addOption(initOpt).
-                addOption(help).addOption(upgradeFromOpt).
-                addOption(initToOpt).addOption(infoOpt);
-    optGroup.setRequired(true);
-
-    Option userNameOpt = OptionBuilder.withArgName("user")
-                .hasArg()
-                .withDescription("Override config file user name")
-                .create("userName");
-    Option passwdOpt = OptionBuilder.withArgName("password")
-                .hasArg()
-                 .withDescription("Override config file password")
-                 .create("passWord");
-    Option dbTypeOpt = OptionBuilder.withArgName("databaseType")
-                .hasArg().withDescription("Metastore database type [" +
-                SentrySchemaHelper.DB_DERBY + "," +
-                SentrySchemaHelper.DB_MYSQL + "," +
-                SentrySchemaHelper.DB_ORACLE + "," +
-                SentrySchemaHelper.DB_POSTGRACE + "," +
-                SentrySchemaHelper.DB_DB2 + "]")
-                .create("dbType");
-    Option dbOpts = OptionBuilder.withArgName("databaseOpts")
-                .hasArgs().withDescription("Backend DB specific options")
-                .create("dbOpts");
-
-    Option dryRunOpt = new Option("dryRun", "list SQL scripts (no execute)");
-    Option verboseOpt = new Option("verbose", "only print SQL statements");
-
-    Option configOpt = OptionBuilder.withArgName("confName").hasArgs()
-        .withDescription("Sentry Service configuration file").isRequired(true)
-        .create(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
-
-    cmdLineOptions.addOption(help);
-    cmdLineOptions.addOption(dryRunOpt);
-    cmdLineOptions.addOption(userNameOpt);
-    cmdLineOptions.addOption(passwdOpt);
-    cmdLineOptions.addOption(dbTypeOpt);
-    cmdLineOptions.addOption(verboseOpt);
-    cmdLineOptions.addOption(dbOpts);
-    cmdLineOptions.addOption(configOpt);
-    cmdLineOptions.addOptionGroup(optGroup);
-  }
-
-  public static class CommandImpl implements Command {
-    @Override
-    public void run(String[] args) throws Exception {
-      CommandLineParser parser = new GnuParser();
-      CommandLine line = null;
-      String dbType = null;
-      String schemaVer = null;
-      Options cmdLineOptions = new Options();
-      String configFileName = null;
-
-      // Argument handling
-      initOptions(cmdLineOptions);
-      try {
-        line = parser.parse(cmdLineOptions, args);
-      } catch (ParseException e) {
-        System.err.println("SentrySchemaTool:Parsing failed.  Reason: "
-            + e.getLocalizedMessage());
-        printAndExit(cmdLineOptions);
-      }
-
-      if (line.hasOption("help")) {
-        HelpFormatter formatter = new HelpFormatter();
-        formatter.printHelp("schemaTool", cmdLineOptions);
-        return;
-      }
-
-      if (line.hasOption("dbType")) {
-        dbType = line.getOptionValue("dbType");
-        if (!dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DERBY)
-            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_MYSQL)
-            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_POSTGRACE)
-            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_ORACLE)
-            && !dbType.equalsIgnoreCase(SentrySchemaHelper.DB_DB2)) {
-          System.err.println("Unsupported dbType " + dbType);
-          printAndExit(cmdLineOptions);
-        }
-      } else {
-        System.err.println("no dbType supplied");
-        printAndExit(cmdLineOptions);
-      }
-      if (line.hasOption(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG)) {
-        configFileName = line
-            .getOptionValue(ServiceConstants.ServiceArgs.CONFIG_FILE_LONG);
-      } else {
-        System.err.println("no config file specified");
-        printAndExit(cmdLineOptions);
-      }
-      try {
-        SentrySchemaTool schemaTool = new SentrySchemaTool(
-            SentryService.loadConfig(configFileName), dbType);
-
-        if (line.hasOption("userName")) {
-          schemaTool.setUserName(line.getOptionValue("userName"));
-        }
-        if (line.hasOption("passWord")) {
-          schemaTool.setPassWord(line.getOptionValue("passWord"));
-        }
-        if (line.hasOption("dryRun")) {
-          schemaTool.setDryRun(true);
-        }
-        if (line.hasOption("verbose")) {
-          schemaTool.setVerbose(true);
-        }
-        if (line.hasOption("dbOpts")) {
-          schemaTool.setDbOpts(line.getOptionValue("dbOpts"));
-        }
-
-        if (line.hasOption("info")) {
-          schemaTool.showInfo();
-        } else if (line.hasOption("upgradeSchema")) {
-          schemaTool.doUpgrade();
-        } else if (line.hasOption("upgradeSchemaFrom")) {
-          schemaVer = line.getOptionValue("upgradeSchemaFrom");
-          schemaTool.doUpgrade(schemaVer);
-        } else if (line.hasOption("initSchema")) {
-          schemaTool.doInit();
-        } else if (line.hasOption("initSchemaTo")) {
-          schemaVer = line.getOptionValue("initSchemaTo");
-          schemaTool.doInit(schemaVer);
-        } else {
-          System.err.println("no valid option supplied");
-          printAndExit(cmdLineOptions);
-        }
-      } catch (SentryUserException e) {
-        System.err.println(e);
-        if (line.hasOption("verbose")) {
-          e.printStackTrace();
-        }
-        System.err.println("*** Sentry schemaTool failed ***");
-        System.exit(1);
-      } catch (MalformedURLException e) {
-        System.err.println(e);
-        if (line.hasOption("verbose")) {
-          e.printStackTrace();
-        }
-        System.err.println("*** Sentry schemaTool failed ***");
-        System.exit(1);
-      }
-      System.out.println("Sentry schemaTool completed");
-    }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java
deleted file mode 100644
index c8b2eef..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellCommon.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/**
- * 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.sentry.provider.db.tools;
-
-import com.google.common.annotations.VisibleForTesting;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.GnuParser;
-import org.apache.commons.cli.HelpFormatter;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionGroup;
-import org.apache.commons.cli.Options;
-import org.apache.commons.cli.ParseException;
-import org.apache.commons.cli.Parser;
-import org.apache.commons.lang.StringUtils;
-
-/**
- * SentryShellCommon provides the function for parsing the argument.
- * For hive model and generic model, child class should be implemented as a sentry admin tool.
- */
-abstract public class SentryShellCommon {
-
-  public enum TYPE { kafka, hive, solr, sqoop };
-
-  public static final String OPTION_DESC_HELP = "Shell usage";
-  public static final String OPTION_DESC_CONF = "sentry-site file path";
-  public static final String OPTION_DESC_ROLE_NAME = "Role name";
-  public static final String OPTION_DESC_GROUP_NAME = "Group name";
-  public static final String OPTION_DESC_PRIVILEGE = "Privilege string";
-  public final static String OPTION_DESC_SERVICE = "Name of the service being managed";
-  public static final String PREFIX_MESSAGE_MISSING_OPTION = "Missing required option: ";
-
-  public static final String GROUP_SPLIT_CHAR = ",";
-
-  protected String roleName;
-  protected String serviceName;
-  protected String groupName;
-  protected String privilegeStr;
-  protected String confPath;
-  // flag for the command
-  protected boolean isCreateRole;
-  protected boolean isDropRole;
-  protected boolean isAddRoleGroup;
-  protected boolean isDeleteRoleGroup;
-  protected boolean isGrantPrivilegeRole;
-  protected boolean isRevokePrivilegeRole;
-  protected boolean isListRole;
-  protected boolean isListPrivilege;
-  protected boolean isListGroup;
-  protected boolean isPrintHelp;
-  // flag for the parameter check
-  protected boolean roleNameRequired;
-  protected boolean groupNameRequired;
-  protected boolean privilegeStrRequired;
-  protected TYPE type;
-
-  /**
-   * parse arguments
-   *
-   * <pre>
-   *   -conf,--sentry_conf             <filepath>                 sentry config file path
-   *   -cr,--create_role            -r <rolename>                 create role
-   *   -dr,--drop_role              -r <rolename>                 drop role
-   *   -arg,--add_role_group        -r <rolename>  -g <groupname> add role to group
-   *   -drg,--delete_role_group     -r <rolename>  -g <groupname> delete role from group
-   *   -gpr,--grant_privilege_role  -r <rolename>  -p <privilege> grant privilege to role
-   *   -rpr,--revoke_privilege_role -r <rolename>  -p <privilege> revoke privilege from role
-   *   -lr,--list_role              -g <groupname>                list roles for group
-   *   -lp,--list_privilege         -r <rolename>                 list privilege for role
-   *   -lg,--list_group                                           list all groups associated with all roles
-   *   -t,--type                    <typename>                    the shell for hive model or generic model
-   * </pre>
-   *
-   * @param args
-   */
-  protected boolean parseArgs(String[] args) {
-    Options simpleShellOptions = new Options();
-
-    setupOptions(simpleShellOptions);
-
-
-
-    // help option
-    Option helpOpt = new Option("h", "help", false, OPTION_DESC_HELP);
-    helpOpt.setRequired(false);
-    simpleShellOptions.addOption(helpOpt);
-
-    // this Options is parsed first for help option
-    Options helpOptions = new Options();
-    helpOptions.addOption(helpOpt);
-
-    try {
-      Parser parser = new GnuParser();
-
-      // parse help option first
-      CommandLine cmd = parser.parse(helpOptions, args, true);
-      for (Option opt : cmd.getOptions()) {
-        if (opt.getOpt().equals("h")) {
-          // get the help option, print the usage and exit
-          usage(simpleShellOptions);
-          return false;
-        }
-      }
-
-      // without help option
-      cmd = parser.parse(simpleShellOptions, args);
-
-      parseOptions(cmd);
-    } catch (ParseException pe) {
-      System.out.println(pe.getMessage());
-      usage(simpleShellOptions);
-      return false;
-    }
-    return true;
-  }
-
-  protected void setupOptions(Options simpleShellOptions) {
-    OptionGroup simpleShellOptGroup = getMainOptions();
-    simpleShellOptions.addOptionGroup(simpleShellOptGroup);
-
-    Option sOpt = new Option("s", "service", true, OPTION_DESC_SERVICE);
-    sOpt.setRequired(false);
-    simpleShellOptions.addOption(sOpt);
-
-    // optional args
-    Option pOpt = new Option("p", "privilege", true, OPTION_DESC_PRIVILEGE);
-    pOpt.setRequired(false);
-    simpleShellOptions.addOption(pOpt);
-
-    Option gOpt = new Option("g", "groupname", true, OPTION_DESC_GROUP_NAME);
-    gOpt.setRequired(false);
-    simpleShellOptions.addOption(gOpt);
-
-    Option rOpt = new Option("r", "rolename", true, OPTION_DESC_ROLE_NAME);
-    rOpt.setRequired(false);
-    simpleShellOptions.addOption(rOpt);
-
-    // this argument should also be parsed in the bin/sentryShell
-    Option tOpt = new Option("t", "type", true, "[hive|solr|sqoop|.....]");
-    tOpt.setRequired(false);
-    simpleShellOptions.addOption(tOpt);
-
-    // file path of sentry-site
-    Option sentrySitePathOpt = new Option("conf", "sentry_conf", true, OPTION_DESC_CONF);
-    sentrySitePathOpt.setRequired(true);
-    simpleShellOptions.addOption(sentrySitePathOpt);
-  }
-
-  protected OptionGroup getMainOptions() {
-    OptionGroup simpleShellOptGroup = new OptionGroup();
-    Option crOpt = new Option("cr", "create_role", false, "Create role");
-    crOpt.setRequired(false);
-
-    Option drOpt = new Option("dr", "drop_role", false, "Drop role");
-    drOpt.setRequired(false);
-
-    Option argOpt = new Option("arg", "add_role_group", false, "Add role to group");
-    argOpt.setRequired(false);
-
-    Option drgOpt = new Option("drg", "delete_role_group", false, "Delete role from group");
-    drgOpt.setRequired(false);
-
-    Option gprOpt = new Option("gpr", "grant_privilege_role", false, "Grant privilege to role");
-    gprOpt.setRequired(false);
-
-    Option rprOpt = new Option("rpr", "revoke_privilege_role", false, "Revoke privilege from role");
-    rprOpt.setRequired(false);
-
-    Option lrOpt = new Option("lr", "list_role", false, "List role");
-    lrOpt.setRequired(false);
-
-    Option lpOpt = new Option("lp", "list_privilege", false, "List privilege");
-    lpOpt.setRequired(false);
-
-    Option lgOpt = new Option("lg", "list_group", false, "List groups");
-    lgOpt.setRequired(false);
-
-
-    // required args group
-    simpleShellOptGroup.addOption(crOpt);
-    simpleShellOptGroup.addOption(drOpt);
-    simpleShellOptGroup.addOption(argOpt);
-    simpleShellOptGroup.addOption(drgOpt);
-    simpleShellOptGroup.addOption(gprOpt);
-    simpleShellOptGroup.addOption(rprOpt);
-    simpleShellOptGroup.addOption(lrOpt);
-    simpleShellOptGroup.addOption(lpOpt);
-    simpleShellOptGroup.addOption(lgOpt);
-    simpleShellOptGroup.setRequired(true);
-    return simpleShellOptGroup;
-  }
-
-  protected void parseOptions(CommandLine cmd) throws ParseException {
-    for (Option opt : cmd.getOptions()) {
-      if (opt.getOpt().equals("p")) {
-        privilegeStr = opt.getValue();
-      } else if (opt.getOpt().equals("g")) {
-        groupName = opt.getValue();
-      } else if (opt.getOpt().equals("r")) {
-        roleName = opt.getValue();
-      } else if (opt.getOpt().equals("s")) {
-        serviceName = opt.getValue();
-      } else if (opt.getOpt().equals("cr")) {
-        isCreateRole = true;
-        roleNameRequired = true;
-      } else if (opt.getOpt().equals("dr")) {
-        isDropRole = true;
-        roleNameRequired = true;
-      } else if (opt.getOpt().equals("arg")) {
-        isAddRoleGroup = true;
-        roleNameRequired = true;
-        groupNameRequired = true;
-      } else if (opt.getOpt().equals("drg")) {
-        isDeleteRoleGroup = true;
-        roleNameRequired = true;
-        groupNameRequired = true;
-      } else if (opt.getOpt().equals("gpr")) {
-        isGrantPrivilegeRole = true;
-        roleNameRequired = true;
-        privilegeStrRequired = true;
-      } else if (opt.getOpt().equals("rpr")) {
-        isRevokePrivilegeRole = true;
-        roleNameRequired = true;
-        privilegeStrRequired = true;
-      } else if (opt.getOpt().equals("lr")) {
-        isListRole = true;
-      } else if (opt.getOpt().equals("lp")) {
-        isListPrivilege = true;
-        roleNameRequired = true;
-      } else if (opt.getOpt().equals("lg")) {
-        isListGroup = true;
-      } else if (opt.getOpt().equals("conf")) {
-        confPath = opt.getValue();
-      } else if (opt.getOpt().equals("t")) {
-        type = TYPE.valueOf(opt.getValue());
-      }
-    }
-    checkRequiredParameter(roleNameRequired, roleName, OPTION_DESC_ROLE_NAME);
-    checkRequiredParameter(groupNameRequired, groupName, OPTION_DESC_GROUP_NAME);
-    checkRequiredParameter(privilegeStrRequired, privilegeStr, OPTION_DESC_PRIVILEGE);
-  }
-
-  protected void checkRequiredParameter(boolean isRequired, String paramValue, String paramName) throws ParseException {
-    if (isRequired && StringUtils.isEmpty(paramValue)) {
-      throw new ParseException(PREFIX_MESSAGE_MISSING_OPTION + paramName);
-    }
-  }
-
-  // print usage
-  private void usage(Options sentryOptions) {
-    HelpFormatter formatter = new HelpFormatter();
-    formatter.printHelp("sentryShell", sentryOptions);
-  }
-
-  // hive model and generic model should implement this method
-  public abstract void run() throws Exception;
-
-  @VisibleForTesting
-  public boolean executeShell(String[] args) throws Exception {
-    boolean result = true;
-    if (parseArgs(args)) {
-      run();
-    } else {
-      result = false;
-    }
-    return result;
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java
deleted file mode 100644
index 785e27d..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/SentryShellHive.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * 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.sentry.provider.db.tools;
-
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.provider.db.tools.command.hive.*;
-import org.apache.sentry.service.thrift.SentryServiceClientFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Sets;
-
-/**
- * SentryShellHive is an admin tool, and responsible for the management of repository.
- * The following function are supported:
- * create role, drop role, add group to role, delete group from role, grant privilege to role,
- * revoke privilege from role, list roles for group, list privilege for role.
- */
-public class SentryShellHive extends SentryShellCommon {
-
-  private static final Logger LOGGER = LoggerFactory.getLogger(SentryShellHive.class);
-
-  public void run() throws Exception {
-
-    try(SentryPolicyServiceClient client =
-                SentryServiceClientFactory.create(getSentryConf())) {
-      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
-      String requestorName = ugi.getShortUserName();
-      ShellCommand command = new HiveShellCommand(client);
-
-      // check the requestor name
-      if (StringUtils.isEmpty(requestorName)) {
-        // The exception message will be recorded in the log file.
-        throw new Exception("The requestor name is empty.");
-      }
-
-      if (isCreateRole) {
-        command.createRole(requestorName, roleName);
-      } else if (isDropRole) {
-        command.dropRole(requestorName, roleName);
-      } else if (isAddRoleGroup) {
-        Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
-        command.grantRoleToGroups(requestorName, roleName, groups);
-      } else if (isDeleteRoleGroup) {
-        Set<String> groups = Sets.newHashSet(groupName.split(SentryShellCommon.GROUP_SPLIT_CHAR));
-        command.revokeRoleFromGroups(requestorName, roleName, groups);
-      } else if (isGrantPrivilegeRole) {
-        command.grantPrivilegeToRole(requestorName, roleName, privilegeStr);
-      } else if (isRevokePrivilegeRole) {
-        command.revokePrivilegeFromRole(requestorName, roleName, privilegeStr);
-      } else if (isListRole) {
-        List<String> roles = command.listRoles(requestorName, groupName);
-        for (String role : roles) {
-          System.out.println(role);
-        }
-      } else if (isListPrivilege) {
-        List<String> privileges = command.listPrivileges(requestorName, roleName);
-        for (String privilege : privileges) {
-          System.out.println(privilege);
-        }
-      } else if (isListGroup) {
-        List<String> groups = command.listGroupRoles(requestorName);
-        for (String group : groups) {
-          System.out.println(group);
-        }
-      }
-    }
-  }
-
-  private Configuration getSentryConf() {
-    Configuration conf = new Configuration();
-    conf.addResource(new Path(confPath), true);
-    return conf;
-  }
-
-  public static void main(String[] args) throws Exception {
-    SentryShellHive sentryShell = new SentryShellHive();
-    try {
-      sentryShell.executeShell(args);
-    } catch (Exception e) {
-      LOGGER.error(e.getMessage(), e);
-      Throwable current =  e;
-      // find the first printable message;
-      while (current != null && current.getMessage() == null) {
-        current = current.getCause();
-      }
-
-      if (current != null) {
-        System.out.println("The operation failed." +
-           (current.getMessage() == null ? "" : "  Message: " + current.getMessage()));
-      }
-    }
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/ShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/ShellCommand.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/ShellCommand.java
deleted file mode 100644
index eeb3a23..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/ShellCommand.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * 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.sentry.provider.db.tools;
-
-import java.util.List;
-import java.util.Set;
-
-import org.apache.sentry.core.common.exception.SentryUserException;
-
-/**
- * The interface for all admin commands, eg, CreateRoleCmd. It is independent of the underlying mechanism (i.e. Generic or Hive)
- */
-public interface ShellCommand {
-
-  void createRole(String requestorName, String roleName) throws SentryUserException;
-
-  void dropRole(String requestorName, String roleName) throws SentryUserException;
-
-  void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException;
-
-  void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException;
-
-  void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException;
-
-  void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException;
-
-  List<String> listRoles(String requestorName, String group) throws SentryUserException;
-
-  List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException;
-
-  List<String> listGroupRoles(String requestorName) throws SentryUserException;
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/CommandUtil.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/CommandUtil.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/CommandUtil.java
deleted file mode 100644
index 3f0b5fa..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/CommandUtil.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * 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.sentry.provider.db.tools.command.hive;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
-import org.apache.sentry.service.thrift.ServiceConstants;
-
-public final class CommandUtil {
-
-  public static final String SPLIT_CHAR = ",";
-
-  private CommandUtil() {
-    // Make constructor private to avoid instantiation
-  }
-
-  // check the privilege value for the specific privilege scope
-  // eg, for the table scope, server and database can't be empty
-  public static void validatePrivilegeHierarchy(TSentryPrivilege tSentryPrivilege) throws IllegalArgumentException {
-    String serverName = tSentryPrivilege.getServerName();
-    String dbName = tSentryPrivilege.getDbName();
-    String tableName = tSentryPrivilege.getTableName();
-    String columnName = tSentryPrivilege.getColumnName();
-    String uri = tSentryPrivilege.getURI();
-    if (ServiceConstants.PrivilegeScope.SERVER.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
-      if (StringUtils.isEmpty(serverName)) {
-        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
-      }
-    } else if (ServiceConstants.PrivilegeScope.URI.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
-      if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(uri)) {
-        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
-      }
-    } else if (ServiceConstants.PrivilegeScope.DATABASE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
-      if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)) {
-        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
-      }
-    } else if (ServiceConstants.PrivilegeScope.TABLE.toString().equals(tSentryPrivilege.getPrivilegeScope())) {
-      if (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)
-              || StringUtils.isEmpty(tableName)) {
-        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
-      }
-    } else if (ServiceConstants.PrivilegeScope.COLUMN.toString().equals(tSentryPrivilege.getPrivilegeScope())
-      && (StringUtils.isEmpty(serverName) || StringUtils.isEmpty(dbName)
-              || StringUtils.isEmpty(tableName) || StringUtils.isEmpty(columnName))) {
-        throw new IllegalArgumentException("The hierarchy of privilege is not correct.");
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/HiveShellCommand.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/HiveShellCommand.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/HiveShellCommand.java
deleted file mode 100644
index 3abba52..0000000
--- a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/tools/command/hive/HiveShellCommand.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * 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.sentry.provider.db.tools.command.hive;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.db.service.thrift.SentryPolicyServiceClient;
-import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
-import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.service.thrift.TSentryRole;
-import org.apache.sentry.provider.db.tools.ShellCommand;
-import org.apache.sentry.service.thrift.SentryServiceUtil;
-
-/**
- * The ShellCommand implementation for Hive.
- */
-public class HiveShellCommand implements ShellCommand {
-
-  private final SentryPolicyServiceClient client;
-
-  public HiveShellCommand(SentryPolicyServiceClient client) {
-    this.client = client;
-  }
-
-  public void createRole(String requestorName, String roleName) throws SentryUserException {
-    client.createRole(requestorName, roleName);
-  }
-
-  public void dropRole(String requestorName, String roleName) throws SentryUserException {
-    client.dropRole(requestorName, roleName);
-  }
-
-  public void grantPrivilegeToRole(String requestorName, String roleName, String privilege) throws SentryUserException {
-    TSentryPrivilege tSentryPrivilege = SentryServiceUtil.convertToTSentryPrivilege(privilege);
-    CommandUtil.validatePrivilegeHierarchy(tSentryPrivilege);
-    client.grantPrivilege(requestorName, roleName, tSentryPrivilege);
-  }
-
-  public void grantRoleToGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
-    client.grantRoleToGroups(requestorName, roleName, groups);
-  }
-
-  public void revokePrivilegeFromRole(String requestorName, String roleName, String privilege) throws SentryUserException {
-    TSentryPrivilege tSentryPrivilege = SentryServiceUtil.convertToTSentryPrivilege(privilege);
-    CommandUtil.validatePrivilegeHierarchy(tSentryPrivilege);
-    client.revokePrivilege(requestorName, roleName, tSentryPrivilege);
-  }
-
-  public void revokeRoleFromGroups(String requestorName, String roleName, Set<String> groups) throws SentryUserException {
-    client.revokeRoleFromGroups(requestorName, roleName, groups);
-  }
-
-  public List<String> listRoles(String requestorName, String group) throws SentryUserException {
-    Set<TSentryRole> roles;
-    if (StringUtils.isEmpty(group)) {
-      roles = client.listAllRoles(requestorName);
-    } else {
-      roles = client.listRolesByGroupName(requestorName, group);
-    }
-
-    List<String> result = new ArrayList<>();
-    if (roles != null) {
-      for (TSentryRole role : roles) {
-        result.add(role.getRoleName());
-      }
-    }
-
-    return result;
-  }
-
-  public List<String> listPrivileges(String requestorName, String roleName) throws SentryUserException {
-    Set<TSentryPrivilege> privileges = client
-        .listAllPrivilegesByRoleName(requestorName, roleName);
-
-    List<String> result = new ArrayList<>();
-    if (privileges != null) {
-      for (TSentryPrivilege privilege : privileges) {
-        String privilegeStr = SentryServiceUtil.convertTSentryPrivilegeToStr(privilege);
-        result.add(privilegeStr);
-      }
-    }
-    return result;
-  }
-
-  public List<String> listGroupRoles(String requestorName) throws SentryUserException {
-    Set<TSentryRole> roles = client.listAllRoles(requestorName);
-    if (roles == null || roles.isEmpty()) {
-      return Collections.emptyList();
-    }
-
-    // Set of all group names
-    Set<String> groupNames = new HashSet<>();
-
-    // Map group to set of roles
-    Map<String, Set<String>> groupInfo = new HashMap<>();
-
-    // Get all group names
-    for (TSentryRole role: roles) {
-      for (TSentryGroup group : role.getGroups()) {
-        String groupName = group.getGroupName();
-        groupNames.add(groupName);
-        Set<String> groupRoles = groupInfo.get(groupName);
-        if (groupRoles != null) {
-          // Add a new or existing role
-          groupRoles.add(role.getRoleName());
-          continue;
-        }
-        // Never seen this group before
-        groupRoles = new HashSet<>();
-        groupRoles.add(role.getRoleName());
-        groupInfo.put(groupName, groupRoles);
-      }
-    }
-
-    List<String> groups = new ArrayList<>(groupNames);
-
-    // Produce printable result as
-    // group1 = role1, role2, ...
-    // group2 = ...
-    List<String> result = new LinkedList<>();
-    for (String groupName: groups) {
-      result.add(groupName + " = " + StringUtils.join(groupInfo.get(groupName), ", "));
-    }
-
-    return result;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestPermissionsMigrationToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestPermissionsMigrationToolSolr.java b/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestPermissionsMigrationToolSolr.java
deleted file mode 100644
index 69c067f..0000000
--- a/sentry-provider/sentry-provider-db/src/test/java/org/apache/sentry/provider/db/generic/tools/TestPermissionsMigrationToolSolr.java
+++ /dev/null
@@ -1,362 +0,0 @@
- /**
- * 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.sentry.provider.db.generic.tools;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.sentry.core.common.exception.SentryUserException;
-import org.apache.sentry.provider.common.ProviderBackendContext;
-import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceIntegrationBase;
-import org.apache.sentry.provider.db.generic.service.thrift.TAuthorizable;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
-import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
-import org.apache.sentry.provider.file.PolicyFile;
-import org.apache.sentry.provider.file.SimpleFileProviderBackend;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
-import com.google.common.io.Files;
-
-public class TestPermissionsMigrationToolSolr extends SentryGenericServiceIntegrationBase {
-  private File confDir;
-  private File confPath;
-  private String requestorName = "";
-  private String service = "service1";
-
-  @Before
-  public void prepareForTest() throws Exception {
-    confDir = Files.createTempDir();
-    confPath = new File(confDir, "sentry-site.xml");
-    if (confPath.createNewFile()) {
-      FileOutputStream to = new FileOutputStream(confPath);
-      conf.writeXml(to);
-      to.close();
-    }
-    requestorName = clientUgi.getShortUserName();//System.getProperty("user.name", "");
-    Set<String> requestorUserGroupNames = Sets.newHashSet(ADMIN_GROUP);
-    setLocalGroupMapping(requestorName, requestorUserGroupNames);
-    // add ADMIN_USER for the after() in SentryServiceIntegrationBase
-    setLocalGroupMapping(ADMIN_USER, requestorUserGroupNames);
-    setLocalGroupMapping("dev", Sets.newHashSet("dev_group"));
-    setLocalGroupMapping("user", Sets.newHashSet("user_group"));
-    writePolicyFile();
-  }
-
-  @After
-  public void clearTestData() throws Exception {
-    FileUtils.deleteQuietly(confDir);
-
-    // clear roles and privileges
-    Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
-    for (TSentryRole tRole : tRoles) {
-      String role = tRole.getRoleName();
-      Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
-          requestorName, role, SOLR, service);
-      for (TSentryPrivilege privilege : privileges) {
-        client.revokePrivilege(requestorName, role, SOLR, privilege);
-      }
-      client.dropRole(requestorName, role, SOLR);
-    }
-  }
-
-  @Test
-  public void testPermissionsMigrationFromSentrySvc_v1() throws Exception {
-    initializeSentryService();
-
-    String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath()};
-    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
-    sentryTool.executeConfigTool(args);
-
-    Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
-    groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
-    groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
-    groupMapping.put("user_role", Sets.newHashSet("user_group"));
-
-    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
-    privilegeMapping.put("admin_role",
-        Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*"));
-    privilegeMapping.put("dev_role",
-        Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*"));
-    privilegeMapping.put("user_role",
-        Sets.newHashSet("collection=foo->action=*"));
-
-    verifySentryServiceState(groupMapping, privilegeMapping);
-  }
-
-  @Test
-  public void testPermissionsMigrationFromSentryPolicyFile_v1() throws Exception {
-    Path policyFilePath = initializeSentryPolicyFile();
-    Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini");
-
-    String[] args = { "-s", "1.8.0", "-p", policyFilePath.toFile().getAbsolutePath(),
-                      "-o", outputFilePath.toFile().getAbsolutePath() };
-    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
-    assertTrue(sentryTool.executeConfigTool(args));
-
-    Set<String> groups = new HashSet<>();
-    groups.add("admin_group");
-    groups.add("dev_group");
-    groups.add("user_group");
-
-    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
-    privilegeMapping.put("admin_role",
-        Sets.newHashSet("admin=collections->action=*", "admin=cores->action=*"));
-    privilegeMapping.put("dev_role",
-        Sets.newHashSet("collection=*->action=*", "admin=collections->action=*", "admin=cores->action=*"));
-    privilegeMapping.put("user_role",
-        Sets.newHashSet("collection=foo->action=*"));
-
-    verifySentryPolicyFile(groups, privilegeMapping, outputFilePath);
-  }
-
-  @Test
-  // For permissions created with Sentry 2.x, no migration necessary
-  public void testPermissionsMigrationFromSentrySvc_v2() throws Exception {
-    initializeSentryService();
-
-    String[] args = { "-s", "2.0.0", "-c", confPath.getAbsolutePath()};
-    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
-    sentryTool.executeConfigTool(args);
-
-    Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
-    groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
-    groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
-    groupMapping.put("user_role", Sets.newHashSet("user_group"));
-
-    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
-    privilegeMapping.put("admin_role",
-        Sets.newHashSet("collection=admin->action=*"));
-    privilegeMapping.put("dev_role",
-        Sets.newHashSet("collection=*->action=*"));
-    privilegeMapping.put("user_role",
-        Sets.newHashSet("collection=foo->action=*"));
-
-    verifySentryServiceState(groupMapping, privilegeMapping);
-  }
-
-  @Test
-  // For permissions created with Sentry 2.x, no migration necessary
-  public void testPermissionsMigrationFromSentryPolicyFile_v2() throws Exception {
-    Path policyFilePath = initializeSentryPolicyFile();
-    Path outputFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider_migrated.ini");
-
-    String[] args = { "-s", "2.0.0", "-p", policyFilePath.toFile().getAbsolutePath(),
-                      "-o", outputFilePath.toFile().getAbsolutePath() };
-    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
-    assertTrue(sentryTool.executeConfigTool(args));
-
-    Set<String> groups = new HashSet<>();
-    groups.add("admin_group");
-    groups.add("dev_group");
-    groups.add("user_group");
-
-    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
-    privilegeMapping.put("admin_role",
-        Sets.newHashSet("collection=admin->action=*"));
-    privilegeMapping.put("dev_role",
-        Sets.newHashSet("collection=*->action=*"));
-    privilegeMapping.put("user_role",
-        Sets.newHashSet("collection=foo->action=*"));
-
-    verifySentryPolicyFile(groups, privilegeMapping, outputFilePath);
-  }
-
-  @Test
-  public void testDryRunOption() throws Exception {
-    initializeSentryService();
-
-    String[] args = { "-s", "1.8.0", "-c", confPath.getAbsolutePath(), "--dry_run"};
-    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
-    sentryTool.executeConfigTool(args);
-
-    Map<String, Set<String>> groupMapping = new HashMap<String, Set<String>>();
-    groupMapping.put("admin_role", Sets.newHashSet("admin_group"));
-    groupMapping.put("dev_role", Sets.newHashSet("dev_group"));
-    groupMapping.put("user_role", Sets.newHashSet("user_group"));
-
-    // No change in the privileges
-    Map<String, Set<String>> privilegeMapping = new HashMap<String, Set<String>>();
-    privilegeMapping.put("admin_role",
-        Sets.newHashSet("collection=admin->action=*"));
-    privilegeMapping.put("dev_role",
-        Sets.newHashSet("collection=*->action=*"));
-    privilegeMapping.put("user_role",
-        Sets.newHashSet("collection=foo->action=*"));
-
-    verifySentryServiceState(groupMapping, privilegeMapping);
-  }
-
-  @Test
-  public void testInvalidToolArguments() throws Exception {
-    PermissionsMigrationToolSolr sentryTool = new PermissionsMigrationToolSolr();
-
-    {
-      String[] args = { "-c", confPath.getAbsolutePath()};
-      assertFalse("The execution should have failed due to missing source version",
-          sentryTool.executeConfigTool(args));
-    }
-
-    {
-      String[] args = { "-s", "1.8.0" };
-      sentryTool.executeConfigTool(args);
-      assertFalse("The execution should have failed due to missing Sentry config file"
-          + " (or policy file) path",
-          sentryTool.executeConfigTool(args));
-    }
-
-    {
-      String[] args = { "-s", "1.8.0", "-p", "/test/path" };
-      sentryTool.executeConfigTool(args);
-      assertFalse("The execution should have failed due to missing Sentry config output file path",
-          sentryTool.executeConfigTool(args));
-    }
-
-    {
-      String[] args = { "-s", "1.8.0", "-c", "/test/path1", "-p", "/test/path2" };
-      sentryTool.executeConfigTool(args);
-      assertFalse("The execution should have failed due to providing both Sentry config file"
-          + " as well as policy file params",
-          sentryTool.executeConfigTool(args));
-    }
-  }
-
-  private void initializeSentryService() throws SentryUserException {
-    // Define an admin role
-    client.createRoleIfNotExist(requestorName, "admin_role", SOLR);
-    client.grantRoleToGroups(requestorName, "admin_role", SOLR, Sets.newHashSet("admin_group"));
-
-    // Define a developer role
-    client.createRoleIfNotExist(requestorName, "dev_role", SOLR);
-    client.grantRoleToGroups(requestorName, "dev_role", SOLR, Sets.newHashSet("dev_group"));
-
-    // Define a user role
-    client.createRoleIfNotExist(requestorName, "user_role", SOLR);
-    client.grantRoleToGroups(requestorName, "user_role", SOLR, Sets.newHashSet("user_group"));
-
-    // Grant permissions
-    client.grantPrivilege(requestorName, "admin_role", SOLR,
-        new TSentryPrivilege(SOLR, "service1",
-            Arrays.asList(new TAuthorizable("collection", "admin")), "*"));
-    client.grantPrivilege(requestorName, "dev_role", SOLR,
-        new TSentryPrivilege(SOLR, "service1",
-            Arrays.asList(new TAuthorizable("collection", "*")), "*"));
-    client.grantPrivilege(requestorName, "user_role", SOLR,
-        new TSentryPrivilege(SOLR, "service1",
-            Arrays.asList(new TAuthorizable("collection", "foo")), "*"));
-  }
-
-  private void verifySentryServiceState(Map<String, Set<String>> groupMapping,
-      Map<String, Set<String>> privilegeMapping) throws SentryUserException {
-    // check roles
-    Set<TSentryRole> tRoles = client.listAllRoles(requestorName, SOLR);
-    assertEquals("Unexpected number of roles", groupMapping.keySet().size(), tRoles.size());
-    Set<String> roles = new HashSet<String>();
-    for (TSentryRole tRole : tRoles) {
-      roles.add(tRole.getRoleName());
-    }
-
-    for (String expectedRole : groupMapping.keySet()) {
-      assertTrue("Didn't find expected role: " + expectedRole, roles.contains(expectedRole));
-    }
-
-    // check groups
-    for (TSentryRole tRole : tRoles) {
-      Set<String> expectedGroups = groupMapping.get(tRole.getRoleName());
-      assertEquals("Group size doesn't match for role: " + tRole.getRoleName(),
-          expectedGroups.size(), tRole.getGroups().size());
-      assertTrue("Group does not contain all expected members for role: " + tRole.getRoleName(),
-          tRole.getGroups().containsAll(expectedGroups));
-    }
-
-    // check privileges
-    GenericPrivilegeConverter convert = new GenericPrivilegeConverter(SOLR, service);
-    for (String role : roles) {
-      Set<TSentryPrivilege> privileges = client.listAllPrivilegesByRoleName(
-          requestorName, role, SOLR, service);
-      Set<String> expectedPrivileges = privilegeMapping.get(role);
-      assertEquals("Privilege set size doesn't match for role: " + role + " Actual permissions : " + privileges,
-          expectedPrivileges.size(), privileges.size());
-
-      Set<String> privilegeStrs = new HashSet<String>();
-      for (TSentryPrivilege privilege : privileges) {
-        privilegeStrs.add(convert.toString(privilege).toLowerCase());
-      }
-
-      for (String expectedPrivilege : expectedPrivileges) {
-        assertTrue("Did not find expected privilege: " + expectedPrivilege + " in " + privilegeStrs,
-            privilegeStrs.contains(expectedPrivilege));
-      }
-    }
-  }
-
-  private Path initializeSentryPolicyFile() throws Exception {
-    PolicyFile file = new PolicyFile();
-
-    file.addRolesToGroup("admin_group", "admin_role");
-    file.addRolesToGroup("dev_group", "dev_role");
-    file.addRolesToGroup("user_group", "user_role");
-
-    file.addPermissionsToRole("admin_role", "collection=admin->action=*");
-    file.addPermissionsToRole("dev_role", "collection=*->action=*");
-    file.addPermissionsToRole("user_role", "collection=foo->action=*");
-
-    Path policyFilePath = Paths.get(confDir.getAbsolutePath(), "sentry-provider.ini");
-    file.write(policyFilePath.toFile());
-
-    return policyFilePath;
-  }
-
-  private void verifySentryPolicyFile (Set<String> groups, Map<String, Set<String>> privilegeMapping,
-      Path policyFilePath) throws IOException {
-    SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf,
-        new org.apache.hadoop.fs.Path(policyFilePath.toUri()));
-    policyFileBackend.initialize(new ProviderBackendContext());
-    Table<String, String, Set<String>> groupRolePrivilegeTable =
-        policyFileBackend.getGroupRolePrivilegeTable();
-
-    assertEquals(groups, groupRolePrivilegeTable.rowKeySet());
-    assertEquals(privilegeMapping.keySet(), groupRolePrivilegeTable.columnKeySet());
-
-    for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
-      for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
-        if (groupRolePrivilegeTable.contains(groupName, roleName)) {
-          Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
-          assertEquals(privilegeMapping.get(roleName), privileges);
-        }
-      }
-    }
-  }
-}


[5/9] sentry git commit: SENTRY-2207 Refactor out Sentry CLI from sentry-provider-db into own module. Steve Moist, reviewed by Colm O hEigeartaigh.

Posted by co...@apache.org.
http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/indexer_config_import_tool.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/indexer_config_import_tool.ini b/sentry-provider/sentry-provider-db/src/test/resources/indexer_config_import_tool.ini
deleted file mode 100644
index c1bfe4b..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/indexer_config_import_tool.ini
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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.
-
-[groups]
-corporal = corporal_role
-sergeant = corporal_role, sergeant_role
-general = corporal_role, sergeant_role, general_role
-commander_in_chief = corporal_role, sergeant_role, general_role, commander_in_chief_role
-
-[roles]
-corporal_role = indexer=info->action=read, \
-  indexer=info->action=write
-sergeant_role = indexer=info->action=write
-general_role = indexer=info->action=*
-commander_in_chief_role = indexer=*

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/indexer_invalid.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/indexer_invalid.ini b/sentry-provider/sentry-provider-db/src/test/resources/indexer_invalid.ini
deleted file mode 100644
index 03083a7..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/indexer_invalid.ini
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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.
-
-[groups]
-
-[roles]
-

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/solr_case.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/solr_case.ini b/sentry-provider/sentry-provider-db/src/test/resources/solr_case.ini
deleted file mode 100644
index fbbebfc..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/solr_case.ini
+++ /dev/null
@@ -1,26 +0,0 @@
-# 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.
-
-[groups]
-groupa = RoLe1
-groupb = rOlE1
-groupc = ROLE2
-
-[roles]
-RoLe1 = collection=*
-rOlE1 = collection=*
-ROLE2 = collection=*

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/solr_config_import_tool.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/solr_config_import_tool.ini b/sentry-provider/sentry-provider-db/src/test/resources/solr_config_import_tool.ini
deleted file mode 100644
index da7df4c..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/solr_config_import_tool.ini
+++ /dev/null
@@ -1,29 +0,0 @@
-# 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.
-
-[groups]
-corporal = corporal_role
-sergeant = corporal_role, sergeant_role
-general = corporal_role, sergeant_role, general_role
-commander_in_chief = corporal_role, sergeant_role, general_role, commander_in_chief_role
-
-[roles]
-corporal_role = collection=info->action=query, \
-  collection=info->action=update
-sergeant_role = collection=info->action=update
-general_role = collection=info->action=*
-commander_in_chief_role = collection=*

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-provider/sentry-provider-db/src/test/resources/solr_invalid.ini
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/test/resources/solr_invalid.ini b/sentry-provider/sentry-provider-db/src/test/resources/solr_invalid.ini
deleted file mode 100644
index 03083a7..0000000
--- a/sentry-provider/sentry-provider-db/src/test/resources/solr_invalid.ini
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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.
-
-[groups]
-
-[roles]
-

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/pom.xml
----------------------------------------------------------------------
diff --git a/sentry-tools/pom.xml b/sentry-tools/pom.xml
index 4d8fc89..b882c6f 100644
--- a/sentry-tools/pom.xml
+++ b/sentry-tools/pom.xml
@@ -26,6 +26,7 @@ limitations under the License.
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>sentry-tools</artifactId>
+    <version>2.1.0-SNAPSHOT</version>
 
     <dependencies>
         <dependency>
@@ -33,27 +34,56 @@ limitations under the License.
             <artifactId>sentry-binding-hive</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-log4j12</artifactId>
+            <groupId>org.apache.sentry</groupId>
+            <artifactId>sentry-provider-db</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sentry</groupId>
+            <artifactId>sentry-provider-db</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>commons-cli</groupId>
             <artifactId>commons-cli</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
             <groupId>com.budhash.cliche</groupId>
             <artifactId>cliche-shell</artifactId>
             <version>0.9.3</version>
         </dependency>
         <dependency>
-            <groupId>org.apache.sentry</groupId>
-            <artifactId>sentry-provider-db</artifactId>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.hadoop</groupId>
+            <artifactId>hadoop-minikdc</artifactId>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 
     <build>
-        <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <reuseForks>false</reuseForks>
+                </configuration>
+            </plugin>
+        </plugins>
+        <testResources>
+            <testResource>
+                <directory>src/test/resources</directory>
+            </testResource>
+        </testResources>
     </build>
-
-
 </project>

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java b/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java
index e92155c..495d4cd 100644
--- a/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java
+++ b/sentry-tools/src/main/java/org/apache/sentry/SentryMain.java
@@ -24,7 +24,7 @@ import org.apache.commons.cli.HelpFormatter;
 import org.apache.commons.cli.Options;
 import org.apache.log4j.PropertyConfigurator;
 import org.apache.sentry.binding.hive.authz.SentryConfigTool;
-import org.apache.sentry.provider.db.tools.SentrySchemaTool;
+import org.apache.sentry.cli.tools.SentrySchemaTool;
 import org.apache.sentry.service.thrift.SentryService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolCommon.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolCommon.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolCommon.java
new file mode 100644
index 0000000..8b5130c
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolCommon.java
@@ -0,0 +1,349 @@
+/**
+ * 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.sentry.cli.tools;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+import java.util.Set;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.Parser;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.core.common.ActiveRoleSet;
+import org.apache.sentry.core.common.utils.PolicyFileConstants;
+import org.apache.sentry.core.common.utils.PolicyFiles;
+import org.apache.sentry.core.common.utils.Version;
+import org.apache.sentry.policy.common.PrivilegeUtils;
+import org.apache.sentry.provider.common.ProviderBackendContext;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.generic.service.thrift.TSentryRole;
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+import org.apache.shiro.config.Ini;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+
+/**
+ * This class provides basic framework required to migrate permissions between different Sentry
+ * versions. Individual components (e.g. SOLR, KAFKA) needs to override the this class
+ * to provide component specific migration functionality.
+ */
+public abstract class PermissionsMigrationToolCommon {
+  private static final Logger LOGGER = LoggerFactory.getLogger(PermissionsMigrationToolCommon.class);
+  public static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
+
+  private Version sourceVersion;
+  private Optional<String> confPath = Optional.empty();
+  private Optional<String> policyFile = Optional.empty();
+  private Optional<String> outputFile = Optional.empty();
+  private boolean dryRun = false;
+
+  /**
+   * @return version of Sentry for which the privileges need to be migrated.
+   */
+  public final Version getSourceVersion() {
+    return sourceVersion;
+  }
+
+  /**
+   * This method returns the name of the component for the migration purpose.
+   * @param conf The Sentry configuration
+   * @return the name of the component
+   */
+  protected abstract String getComponent(Configuration conf);
+
+
+  /**
+   * This method returns the name of the service name for the migration purpose.
+   *
+   * @param conf The Sentry configuration
+   * @return the name of the service
+   */
+  protected abstract String getServiceName(Configuration conf);
+
+  /**
+   * Migrate the privileges specified via <code>privileges</code>.
+   *
+   * @param privileges A collection of privileges to be migrated.
+   * @return A collection of migrated privileges
+   *         An empty collection if migration is not necessary for the specified privileges.
+   */
+  protected abstract Collection<String> transformPrivileges (Collection<String> privileges);
+
+  /**
+   *  parse arguments
+   * <pre>
+   *   -s,--source                   Sentry source version
+   *   -c,--sentry_conf <filepath>   sentry config file path
+   *   -p --policy_file <filepath>   sentry (source) policy file path
+   *   -o --output      <filepath>   sentry (target) policy file path
+   *   -d --dry_run                  provides the output the migration for inspection without
+   *                                 making any configuration changes.
+   *   -h,--help                     print usage
+   * </pre>
+   * @param args
+   */
+  protected boolean parseArgs(String [] args) {
+    Options options = new Options();
+
+    Option sourceVersionOpt = new Option("s", "source", true, "Source Sentry version");
+    sourceVersionOpt.setRequired(true);
+    options.addOption(sourceVersionOpt);
+
+    Option sentryConfPathOpt = new Option("c", "sentry_conf", true,
+        "sentry-site.xml file path (only required in case of Sentry service)");
+    sentryConfPathOpt.setRequired(false);
+    options.addOption(sentryConfPathOpt);
+
+    Option sentryPolicyFileOpt = new Option("p", "policy_file", true,
+        "sentry (source) policy file path (only in case of file based Sentry configuration)");
+    sentryPolicyFileOpt.setRequired(false);
+    options.addOption(sentryPolicyFileOpt);
+
+    Option sentryOutputFileOpt = new Option("o", "output", true,
+        "sentry (target) policy file path (only in case of file based Sentry configuration)");
+    sentryOutputFileOpt.setRequired(false);
+    options.addOption(sentryOutputFileOpt);
+
+    Option dryRunOpt = new Option("d", "dry_run", false,
+        "provides the output the migration for inspection without making actual configuration changes");
+    dryRunOpt.setRequired(false);
+    options.addOption(dryRunOpt);
+
+    // help option
+    Option helpOpt = new Option("h", "help", false, "Shell usage");
+    helpOpt.setRequired(false);
+    options.addOption(helpOpt);
+
+    // this Option is parsed first for help option
+    Options helpOptions = new Options();
+    helpOptions.addOption(helpOpt);
+
+    try {
+      Parser parser = new GnuParser();
+
+      // parse help option first
+      CommandLine cmd = parser.parse(helpOptions, args, true);
+      for (Option opt : cmd.getOptions()) {
+        if (opt.getOpt().equals("h")) {
+          // get the help option, print the usage and exit
+          usage(options);
+          return false;
+        }
+      }
+
+      // without help option
+      cmd = parser.parse(options, args);
+
+      String sourceVersionStr = null;
+
+      for (Option opt : cmd.getOptions()) {
+        if (opt.getOpt().equals("s")) {
+          sourceVersionStr = opt.getValue();
+        } else if (opt.getOpt().equals("c")) {
+          confPath = Optional.of(opt.getValue());
+        } else if (opt.getOpt().equals("p")) {
+          policyFile = Optional.of(opt.getValue());
+        }  else if (opt.getOpt().equals("o")) {
+          outputFile = Optional.of(opt.getValue());
+        }  else if (opt.getOpt().equals("d")) {
+          dryRun = true;
+        }
+      }
+
+      sourceVersion = Version.parse(sourceVersionStr);
+
+      if (!(confPath.isPresent() || policyFile.isPresent())) {
+        System.out.println("Please select either file-based Sentry configuration (-p and -o flags)"
+            + " or Sentry service (-c flag) for migration.");
+        usage(options);
+        return false;
+      }
+
+      if (confPath.isPresent() && (policyFile.isPresent() || outputFile.isPresent())) {
+        System.out.println("In order to migrate service based Sentry configuration,"
+            + " do not specify either -p or -o parameters");
+        usage(options);
+        return false;
+      }
+
+      if (!confPath.isPresent() && (policyFile.isPresent() ^ outputFile.isPresent())) {
+        System.out.println("In order to migrate file based Sentry configuration,"
+            + " please make sure to specify both -p and -o parameters.");
+        usage(options);
+        return false;
+      }
+
+    } catch (ParseException | java.text.ParseException pe) {
+      System.out.println(pe.getMessage());
+      usage(options);
+      return false;
+    }
+    return true;
+  }
+
+  // print usage
+  private void usage(Options sentryOptions) {
+    HelpFormatter formatter = new HelpFormatter();
+    formatter.printHelp("sentryMigrationTool", sentryOptions);
+  }
+
+  public void run() throws Exception {
+    if (policyFile.isPresent()) {
+      migratePolicyFile();
+    } else {
+      migrateSentryServiceConfig();
+    }
+  }
+
+  private void migrateSentryServiceConfig() throws Exception {
+    Configuration conf = getSentryConf();
+    String component = getComponent(conf);
+    String serviceName = getServiceName(conf);
+    GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, serviceName, false);
+
+    // instantiate a client for sentry service.  This sets the ugi, so must
+    // be done before getting the ugi below.
+    try(SentryGenericServiceClient client =
+                SentryGenericServiceClientFactory.create(getSentryConf())) {
+      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+      String requestorName = ugi.getShortUserName();
+
+      for (TSentryRole r : client.listAllRoles(requestorName, component)) {
+        for (TSentryPrivilege p : client.listAllPrivilegesByRoleName(requestorName,
+            r.getRoleName(), component, serviceName)) {
+
+          String privilegeStr = converter.toString(p);
+          Collection<String> privileges = Collections.singleton(privilegeStr);
+          Collection<String> migrated = transformPrivileges(privileges);
+          if (!migrated.isEmpty()) {
+            LOGGER.info("{} For role {} migrating privileges from {} to {}", getDryRunMessage(), r.getRoleName(),
+                privileges, migrated);
+
+            /*
+             * Note that it is not possible to provide transactional (all-or-nothing) behavior for these configuration
+             * changes since the Sentry client/server protocol does not support. e.g. under certain failure conditions
+             * like crash of Sentry server or network disconnect between client/server, it is possible that the migration
+             * can not complete but can also not be rolled back. Hence this migration tool relies on the fact that privilege
+             * grant/revoke operations are idempotent and hence re-execution of the migration tool will fix any inconsistency
+             * due to such failures.
+             **/
+            boolean originalPermPresent = false;
+            for (String perm : migrated) {
+              if (perm.equalsIgnoreCase(privilegeStr)) {
+                originalPermPresent = true;
+                continue;
+              }
+              TSentryPrivilege x = converter.fromString(perm);
+              LOGGER.info("{} GRANT permission {}", getDryRunMessage(), perm);
+              if (!dryRun) {
+                client.grantPrivilege(requestorName, r.getRoleName(), component, x);
+              }
+            }
+
+            // Revoke old permission (only if not part of migrated permissions)
+            if (!originalPermPresent) {
+              LOGGER.info("{} REVOKE permission {}", getDryRunMessage(), privilegeStr);
+              if (!dryRun) {
+                client.revokePrivilege(requestorName, r.getRoleName(), component, p);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  private void migratePolicyFile () throws Exception {
+    Configuration conf = getSentryConf();
+    Path sourceFile = new Path (policyFile.get());
+    SimpleFileProviderBackend policyFileBackend = new SimpleFileProviderBackend(conf, sourceFile);
+    ProviderBackendContext ctx = new ProviderBackendContext();
+    policyFileBackend.initialize(ctx);
+
+    Set<String> roles = Sets.newHashSet();
+    Table<String, String, Set<String>> groupRolePrivilegeTable =
+        policyFileBackend.getGroupRolePrivilegeTable();
+
+    Ini output = PolicyFiles.loadFromPath(sourceFile.getFileSystem(conf), sourceFile);
+    Ini.Section rolesSection = output.get(PolicyFileConstants.ROLES);
+
+    for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
+      for (String roleName : policyFileBackend.getRoles(Collections.singleton(groupName), ActiveRoleSet.ALL)) {
+        if (!roles.contains(roleName)) {
+          // Do the actual migration
+          Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
+          Collection<String> migrated = transformPrivileges(privileges);
+
+          if (!migrated.isEmpty()) {
+            LOGGER.info("{} For role {} migrating privileges from {} to {}", getDryRunMessage(),
+                roleName, privileges, migrated);
+            if (!dryRun) {
+              rolesSection.put(roleName, PrivilegeUtils.fromPrivilegeStrings(migrated));
+            }
+          }
+
+          roles.add(roleName);
+        }
+      }
+    }
+
+    if (!dryRun) {
+      Path targetFile = new Path (outputFile.get());
+      PolicyFiles.writeToPath(output, targetFile.getFileSystem(conf), targetFile);
+      LOGGER.info("Successfully saved migrated Sentry policy file at {}", outputFile.get());
+    }
+  }
+
+  private String getDryRunMessage() {
+    return dryRun ? "[Dry Run]" : "";
+  }
+
+  private Configuration getSentryConf() {
+    Configuration conf = new Configuration();
+    if (confPath.isPresent()) {
+      conf.addResource(new Path(confPath.get()), true);
+    }
+    return conf;
+  }
+
+  @VisibleForTesting
+  public boolean executeConfigTool(String [] args) throws Exception {
+    boolean result = true;
+    if (parseArgs(args)) {
+      run();
+    } else {
+      result = false;
+    }
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolSolr.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolSolr.java
new file mode 100644
index 0000000..c24ae93
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/PermissionsMigrationToolSolr.java
@@ -0,0 +1,109 @@
+/**
+ * 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.sentry.cli.tools;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.core.common.utils.SentryConstants;
+import org.apache.sentry.core.model.solr.validator.SolrPrivilegeValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class provides SOLR specific functionality required for migrating Sentry privileges.
+ */
+public class PermissionsMigrationToolSolr extends PermissionsMigrationToolCommon {
+  private static final Logger LOGGER = LoggerFactory.getLogger(PermissionsMigrationToolSolr.class);
+
+
+  @Override
+  protected String getComponent(Configuration conf) {
+    return "SOLR";
+  }
+
+  @Override
+  protected String getServiceName(Configuration conf) {
+    return conf.get(SOLR_SERVICE_NAME, "service1");
+  }
+
+  @Override
+  protected Collection<String> transformPrivileges(Collection<String> privileges) {
+    List<String> result = new ArrayList<>();
+    boolean migrated = false;
+
+    if (getSourceVersion().major == 1) { // Migrate only Sentry 1.x permissions
+      for (String p : privileges) {
+        SolrPrivilegeValidator v = new SolrPrivilegeValidator();
+        v.validate(p, false);
+
+        if ("collection".equalsIgnoreCase(v.getEntityType()) && "admin".equalsIgnoreCase(v.getEntityName())) {
+          result.add(getPermissionStr("admin", "collections", v.getActionName()));
+          result.add(getPermissionStr("admin", "cores", v.getActionName()));
+          migrated = true;
+        } else if ("collection".equalsIgnoreCase(v.getEntityType()) && "*".equals(v.getEntityName())) {
+          result.add(getPermissionStr("admin", "collections", v.getActionName()));
+          result.add(getPermissionStr("admin", "cores", v.getActionName()));
+          result.add(p);
+          migrated = true;
+        } else {
+          result.add(p);
+        }
+      }
+    }
+
+    return migrated ? result : Collections.emptyList();
+  }
+
+  private String getPermissionStr (String entityType, String entityName, String action) {
+    StringBuilder builder = new StringBuilder();
+    builder.append(entityType);
+    builder.append(SentryConstants.KV_SEPARATOR);
+    builder.append(entityName);
+    if (action != null) {
+      builder.append(SentryConstants.AUTHORIZABLE_SEPARATOR);
+      builder.append(SentryConstants.PRIVILEGE_NAME);
+      builder.append(SentryConstants.KV_SEPARATOR);
+      builder.append(action);
+    }
+    return builder.toString();
+  }
+
+  public static void main(String[] args) throws Exception {
+    PermissionsMigrationToolSolr solrTool = new PermissionsMigrationToolSolr();
+    try {
+      solrTool.executeConfigTool(args);
+    } catch (Exception e) {
+      LOGGER.error(e.getMessage(), e);
+      Throwable current = e;
+      // find the first printable message;
+      while (current != null && current.getMessage() == null) {
+        current = current.getCause();
+      }
+      String error = "";
+      if (current != null && current.getMessage() != null) {
+        error = "Message: " + current.getMessage();
+      }
+      System.out.println("The operation failed. " + error);
+      System.exit(1);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolCommon.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolCommon.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolCommon.java
new file mode 100644
index 0000000..2d4f973
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolCommon.java
@@ -0,0 +1,152 @@
+/**
+ * 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.sentry.cli.tools;
+
+import com.google.common.annotations.VisibleForTesting;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+import org.apache.commons.cli.Parser;
+
+abstract public class SentryConfigToolCommon {
+  private String policyFile;
+  private boolean validate;
+  private boolean importPolicy;
+  private boolean checkCompat;
+  private String confPath;
+
+ /**
+   *  parse arguments
+   * <pre>
+   *   -conf,--sentry_conf <filepath>     sentry config file path
+   *   -p,--policy_ini     <arg>          policy file path
+   *   -v,--validate                      validate policy file
+   *   -c,--checkcompat                   check compatibility with service
+   *   -i,--import                        import policy file
+   *   -h,--help                          print usage
+   * </pre>
+   * @param args
+   */
+  protected boolean parseArgs(String [] args) {
+    Options options = new Options();
+
+    Option globalPolicyPath = new Option("p", "policy_ini", true,
+        "Policy file path");
+    globalPolicyPath.setRequired(true);
+    options.addOption(globalPolicyPath);
+
+    Option validateOpt = new Option("v", "validate", false,
+        "Validate policy file");
+    validateOpt.setRequired(false);
+    options.addOption(validateOpt);
+
+    Option checkCompatOpt = new Option("c","checkcompat",false,
+        "Check compatibility with Sentry Service");
+    checkCompatOpt.setRequired(false);
+    options.addOption(checkCompatOpt);
+
+    Option importOpt = new Option("i", "import", false,
+        "Import policy file");
+    importOpt.setRequired(false);
+    options.addOption(importOpt);
+
+    // file path of sentry-site
+    Option sentrySitePathOpt = new Option("conf", "sentry_conf", true, "sentry-site file path");
+    sentrySitePathOpt.setRequired(true);
+    options.addOption(sentrySitePathOpt);
+
+    // help option
+    Option helpOpt = new Option("h", "help", false, "Shell usage");
+    helpOpt.setRequired(false);
+    options.addOption(helpOpt);
+
+    // this Options is parsed first for help option
+    Options helpOptions = new Options();
+    helpOptions.addOption(helpOpt);
+
+    try {
+      Parser parser = new GnuParser();
+
+      // parse help option first
+      CommandLine cmd = parser.parse(helpOptions, args, true);
+      for (Option opt : cmd.getOptions()) {
+        if (opt.getOpt().equals("h")) {
+          // get the help option, print the usage and exit
+          usage(options);
+          return false;
+        }
+      }
+
+      // without help option
+      cmd = parser.parse(options, args);
+
+      for (Option opt : cmd.getOptions()) {
+        if (opt.getOpt().equals("p")) {
+          policyFile = opt.getValue();
+        } else if (opt.getOpt().equals("v")) {
+          validate = true;
+        } else if (opt.getOpt().equals("i")) {
+          importPolicy = true;
+        } else if (opt.getOpt().equals("c")) {
+          checkCompat = true;
+        } else if (opt.getOpt().equals("conf")) {
+          confPath = opt.getValue();
+        }
+      }
+
+      if (!validate && !importPolicy) {
+        throw new IllegalArgumentException("No action specified; at least one of action or import must be specified");
+      }
+    } catch (ParseException pe) {
+      System.out.println(pe.getMessage());
+      usage(options);
+      return false;
+    }
+    return true;
+  }
+
+  // print usage
+  private void usage(Options sentryOptions) {
+    HelpFormatter formatter = new HelpFormatter();
+    formatter.printHelp("sentryConfigTool", sentryOptions);
+  }
+
+  public abstract void run() throws Exception;
+
+  @VisibleForTesting
+  public boolean executeConfigTool(String [] args) throws Exception {
+    boolean result = true;
+    if (parseArgs(args)) {
+      run();
+    } else {
+      result = false;
+    }
+    return result;
+  }
+
+  public String getPolicyFile() { return policyFile; }
+  public boolean getValidate() { return validate; }
+  public boolean getImportPolicy() { return importPolicy; }
+  public boolean getCheckCompat() { return checkCompat; }
+  public String getConfPath() { return confPath; }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolIndexer.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolIndexer.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolIndexer.java
new file mode 100644
index 0000000..712d9ed
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolIndexer.java
@@ -0,0 +1,341 @@
+/**
+ * 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.sentry.cli.tools;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.core.common.Action;
+import org.apache.sentry.core.common.exception.SentryConfigurationException;
+import org.apache.sentry.core.common.utils.KeyValue;
+import org.apache.sentry.core.model.indexer.IndexerPrivilegeModel;
+import org.apache.sentry.provider.common.ProviderBackend;
+import org.apache.sentry.provider.common.ProviderBackendContext;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.sentry.core.common.utils.SentryConstants.AUTHORIZABLE_SPLITTER;
+import static org.apache.sentry.provider.common.AuthorizationComponent.HBASE_INDEXER;
+import static org.apache.sentry.service.thrift.ServiceConstants.ClientConfig.SERVICE_NAME;
+
+/**
+ * SentryConfigToolIndexer is an administrative tool used to parse a HBase Indexer policy file
+ * and add the role, group mappings, and privileges therein to the Sentry service.
+ */
+public class SentryConfigToolIndexer {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(SentryConfigToolIndexer.class);
+
+  private String policyFile;
+  private boolean validate;
+  private boolean importPolicy;
+  private boolean checkCompat;
+  private String confPath;
+
+  private String serviceName;
+
+
+
+  public String getPolicyFile() { return policyFile; }
+
+  public boolean getValidate() { return validate; }
+  public boolean getImportPolicy() { return importPolicy; }
+  public boolean getCheckCompat() { return checkCompat; }
+  public String getConfPath() { return confPath; }
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  /**
+   * Adds command line options for the tool to the passed Options object. Used to extend existing options.
+   * @param options
+   */
+  public void setupOptions(Options options) {
+    Option globalPolicyPath = new Option("f", "policy_ini", true,
+            "Policy file path");
+    globalPolicyPath.setRequired(false);
+    options.addOption(globalPolicyPath);
+
+    Option validateOpt = new Option("v", "validate", false,
+            "Validate policy file");
+    validateOpt.setRequired(false);
+    options.addOption(validateOpt);
+
+    Option checkCompatOpt = new Option("c","checkcompat",false,
+            "Check compatibility with Sentry Service");
+    checkCompatOpt.setRequired(false);
+    options.addOption(checkCompatOpt);
+
+    Option importOpt = new Option("i", "import", false,
+            "Import policy file");
+    importOpt.setRequired(false);
+    options.addOption(importOpt);
+
+  }
+
+  /**
+   * Parses and processes the arguments from the given command line object.
+   * @param cmd
+   */
+  public void parseOptions(CommandLine cmd) {
+    boolean isToolActive = false;
+    for (Option opt : cmd.getOptions()) {
+      if (opt.getOpt().equals("mgr")) {
+        isToolActive = true;
+      }
+    }
+    if (!isToolActive) {
+      return;
+    }
+    for (Option opt : cmd.getOptions()) {
+      if (opt.getOpt().equals("f")) {
+        policyFile = opt.getValue();
+      } else if (opt.getOpt().equals("v")) {
+        validate = true;
+      } else if (opt.getOpt().equals("i")) {
+        importPolicy = true;
+      } else if (opt.getOpt().equals("c")) {
+        checkCompat = true;
+      } else if (opt.getOpt().equals("conf")) {
+        confPath = opt.getValue();
+      } else if (opt.getOpt().equals("s")) {
+        serviceName = opt.getValue();
+      }
+    }
+    if (policyFile == null) {
+      throw new IllegalArgumentException("Missing required option: f");
+    }
+    if (!validate && !importPolicy) {
+      throw new IllegalArgumentException("No action specified; at least one of action or import must be specified");
+    }
+  }
+
+
+  /**
+   * Processes the necessary command based on the arguments parsed earlier.
+   * @throws Exception
+   */
+  public void run() throws Exception {
+    String component = HBASE_INDEXER;
+    Configuration conf = getSentryConf();
+
+    String service = conf.get(SERVICE_NAME, getServiceName());
+
+    if (service == null) {
+      throw new IllegalArgumentException("Service was not defined. Please, use -s command option, or sentry.provider.backend.generic.service-name configuration entry.");
+    }
+
+    LOGGER.info(String.format("Context: component=%s, service=%s", component, service));
+    // instantiate a solr client for sentry service.  This sets the ugi, so must
+    // be done before getting the ugi below.
+    try(SentryGenericServiceClient client =
+                SentryGenericServiceClientFactory.create(conf)) {
+      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+      String requestorName = ugi.getShortUserName();
+
+      convertINIToSentryServiceCmds(component, service, requestorName, conf, client,
+              getPolicyFile(), getValidate(), getImportPolicy(), getCheckCompat());
+    }
+  }
+
+  private Configuration getSentryConf() {
+    Configuration conf = new Configuration();
+    conf.addResource(new Path(getConfPath()), true);
+    return conf;
+  }
+
+  private void convertINIToSentryServiceCmds(String component,
+      String service, String requestorName,
+      Configuration conf, SentryGenericServiceClient client,
+      String policyFile, boolean validate, boolean importPolicy,
+      boolean checkCompat) throws Exception {
+
+    //instantiate a file providerBackend for parsing
+    LOGGER.info("Reading policy file at: " + policyFile);
+    SimpleFileProviderBackend policyFileBackend =
+        new SimpleFileProviderBackend(conf, policyFile);
+    ProviderBackendContext context = new ProviderBackendContext();
+    context.setValidators(IndexerPrivilegeModel.getInstance().getPrivilegeValidators());
+    policyFileBackend.initialize(context);
+    if (validate) {
+      validatePolicy(policyFileBackend);
+    }
+
+    if (checkCompat) {
+      checkCompat(policyFileBackend);
+    }
+
+    //import the relations about group,role and privilege into the DB store
+    Set<String> roles = Sets.newHashSet();
+    Table<String, String, Set<String>> groupRolePrivilegeTable =
+        policyFileBackend.getGroupRolePrivilegeTable();
+    GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, service, false);
+
+    for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
+      for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+        if (!roles.contains(roleName)) {
+          LOGGER.info(dryRunMessage(importPolicy) + "Creating role: " + roleName.toLowerCase(Locale.US));
+          if (importPolicy) {
+            client.createRoleIfNotExist(requestorName, roleName, component);
+          }
+          roles.add(roleName);
+        }
+
+        Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
+        if (privileges == null) {
+          continue;
+        }
+        LOGGER.info(dryRunMessage(importPolicy) + "Adding role: " + roleName.toLowerCase(Locale.US) + " to group: " + groupName);
+        if (importPolicy) {
+          client.grantRoleToGroups(requestorName, roleName, component, Sets.newHashSet(groupName));
+        }
+
+        for (String permission : privileges) {
+          String action = null;
+
+          for (String authorizable : AUTHORIZABLE_SPLITTER.
+              trimResults().split(permission)) {
+            KeyValue kv = new KeyValue(authorizable);
+            String key = kv.getKey();
+            String value = kv.getValue();
+            if ("action".equalsIgnoreCase(key)) {
+              action = value;
+            }
+          }
+
+          // Service doesn't support not specifying action
+          if (action == null) {
+            permission += "->action=" + Action.ALL;
+          }
+          LOGGER.info(dryRunMessage(importPolicy) + "Adding permission: " + permission + " to role: " + roleName.toLowerCase(Locale.US));
+          if (importPolicy) {
+            client.grantPrivilege(requestorName, roleName, component, converter.fromString(permission));
+          }
+        }
+      }
+    }
+  }
+
+  private void validatePolicy(ProviderBackend backend) throws Exception {
+    try {
+      backend.validatePolicy(true);
+    } catch (SentryConfigurationException e) {
+      printConfigErrorsWarnings(e);
+      throw e;
+    }
+  }
+
+  private void printConfigErrorsWarnings(SentryConfigurationException configException) {
+    System.out.println(" *** Found configuration problems *** ");
+    for (String errMsg : configException.getConfigErrors()) {
+      System.out.println("ERROR: " + errMsg);
+    }
+    for (String warnMsg : configException.getConfigWarnings()) {
+      System.out.println("Warning: " + warnMsg);
+    }
+  }
+
+  private void checkCompat(SimpleFileProviderBackend backend) throws Exception {
+    Map<String, Set<String>> rolesCaseMapping = new HashMap<String, Set<String>>();
+    Table<String, String, Set<String>> groupRolePrivilegeTable =
+      backend.getGroupRolePrivilegeTable();
+
+    for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+      String roleNameLower = roleName.toLowerCase(Locale.US);
+      if (!roleName.equals(roleNameLower)) {
+        if (!rolesCaseMapping.containsKey(roleNameLower)) {
+          rolesCaseMapping.put(roleNameLower, Sets.newHashSet(roleName));
+        } else {
+          rolesCaseMapping.get(roleNameLower).add(roleName);
+        }
+      }
+    }
+
+    List<String> errors = new LinkedList<String>();
+    StringBuilder warningString = new StringBuilder();
+    if (!rolesCaseMapping.isEmpty()) {
+      warningString.append("The following roles names will be lower cased when added to the Sentry Service.\n");
+      warningString.append("This will cause document-level security to fail to match the role tokens.\n");
+      warningString.append("Role names: ");
+    }
+    boolean firstWarning = true;
+
+    for (Map.Entry<String, Set<String>> entry : rolesCaseMapping.entrySet()) {
+      Set<String> caseMapping = entry.getValue();
+      if (caseMapping.size() > 1) {
+        StringBuilder errorString = new StringBuilder();
+        errorString.append("The following (cased) roles map to the same role in the sentry service: ");
+        boolean first = true;
+        for (String casedRole : caseMapping) {
+          errorString.append(first ? "" : ", ");
+          errorString.append(casedRole);
+          first = false;
+        }
+        errorString.append(".  Role in service: ").append(entry.getKey());
+        errors.add(errorString.toString());
+      }
+
+      for (String casedRole : caseMapping) {
+        warningString.append(firstWarning? "" : ", ");
+        warningString.append(casedRole);
+        firstWarning = false;
+      }
+    }
+
+    for (String error : errors) {
+      System.out.println("ERROR: " + error);
+    }
+    System.out.println("\n");
+
+    System.out.println("Warning: " + warningString.toString());
+    if (errors.size() > 0) {
+      SentryConfigurationException ex =
+          new SentryConfigurationException("Compatibility check failure");
+      ex.setConfigErrors(errors);
+      ex.setConfigWarnings(Lists.<String>asList(warningString.toString(), new String[0]));
+      throw ex;
+    }
+  }
+
+  private String dryRunMessage(boolean importPolicy) {
+    if (importPolicy) {
+      return "";
+    } else {
+      return "[Dry Run] ";
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolSolr.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolSolr.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolSolr.java
new file mode 100644
index 0000000..dfa981d
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentryConfigToolSolr.java
@@ -0,0 +1,265 @@
+/**
+ * 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.sentry.cli.tools;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Table;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.sentry.core.common.Action;
+import org.apache.sentry.core.common.exception.SentryConfigurationException;
+import org.apache.sentry.core.common.utils.KeyValue;
+import org.apache.sentry.core.common.utils.SentryConstants;
+import org.apache.sentry.core.model.solr.SolrPrivilegeModel;
+import org.apache.sentry.provider.common.ProviderBackend;
+import org.apache.sentry.provider.common.ProviderBackendContext;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClient;
+import org.apache.sentry.provider.db.generic.service.thrift.SentryGenericServiceClientFactory;
+import org.apache.sentry.provider.db.generic.tools.GenericPrivilegeConverter;
+import org.apache.sentry.provider.file.SimpleFileProviderBackend;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * SentryConfigToolSolr is an administrative tool used to parse a Solr policy file
+ * and add the role, group mappings, and privileges therein to the Sentry service.
+ */
+public class SentryConfigToolSolr extends SentryConfigToolCommon {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(SentryConfigToolSolr.class);
+  public static final String SOLR_SERVICE_NAME = "sentry.service.client.solr.service.name";
+
+  @Override
+  public void run() throws Exception {
+    String component = "SOLR";
+    Configuration conf = getSentryConf();
+
+    String service = conf.get(SOLR_SERVICE_NAME, "service1");
+    // instantiate a solr client for sentry service.  This sets the ugi, so must
+    // be done before getting the ugi below.
+    try(SentryGenericServiceClient client =
+                SentryGenericServiceClientFactory.create(conf)) {
+      UserGroupInformation ugi = UserGroupInformation.getLoginUser();
+      String requestorName = ugi.getShortUserName();
+
+      convertINIToSentryServiceCmds(component, service, requestorName, conf, client,
+              getPolicyFile(), getValidate(), getImportPolicy(), getCheckCompat());
+    }
+  }
+
+  private Configuration getSentryConf() {
+    Configuration conf = new Configuration();
+    conf.addResource(new Path(getConfPath()), true);
+    return conf;
+  }
+
+   /**
+    * Convert policy file to solrctl commands -- based on SENTRY-480
+    */
+  private void convertINIToSentryServiceCmds(String component,
+      String service, String requestorName,
+      Configuration conf, SentryGenericServiceClient client,
+      String policyFile, boolean validate, boolean importPolicy,
+      boolean checkCompat) throws Exception {
+
+    //instantiate a file providerBackend for parsing
+    LOGGER.info("Reading policy file at: " + policyFile);
+    SimpleFileProviderBackend policyFileBackend =
+        new SimpleFileProviderBackend(conf, policyFile);
+    ProviderBackendContext context = new ProviderBackendContext();
+    context.setValidators(SolrPrivilegeModel.getInstance().getPrivilegeValidators());
+    policyFileBackend.initialize(context);
+    if (validate) {
+      validatePolicy(policyFileBackend);
+    }
+
+    if (checkCompat) {
+      checkCompat(policyFileBackend);
+    }
+
+    //import the relations about group,role and privilege into the DB store
+    Set<String> roles = Sets.newHashSet();
+    Table<String, String, Set<String>> groupRolePrivilegeTable =
+        policyFileBackend.getGroupRolePrivilegeTable();
+    GenericPrivilegeConverter converter = new GenericPrivilegeConverter(component, service, false);
+
+    for (String groupName : groupRolePrivilegeTable.rowKeySet()) {
+      for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+        if (!roles.contains(roleName)) {
+          LOGGER.info(dryRunMessage(importPolicy) + "Creating role: " + roleName.toLowerCase(Locale.US));
+          if (importPolicy) {
+            client.createRoleIfNotExist(requestorName, roleName, component);
+          }
+          roles.add(roleName);
+        }
+
+        Set<String> privileges = groupRolePrivilegeTable.get(groupName, roleName);
+        if (privileges == null) {
+          continue;
+        }
+        LOGGER.info(dryRunMessage(importPolicy) + "Adding role: " + roleName.toLowerCase(Locale.US) + " to group: " + groupName);
+        if (importPolicy) {
+          client.grantRoleToGroups(requestorName, roleName, component, Sets.newHashSet(groupName));
+        }
+
+        for (String permission : privileges) {
+          String action = null;
+
+          for (String authorizable : SentryConstants.AUTHORIZABLE_SPLITTER.
+              trimResults().split(permission)) {
+            KeyValue kv = new KeyValue(authorizable);
+            String key = kv.getKey();
+            String value = kv.getValue();
+            if ("action".equalsIgnoreCase(key)) {
+              action = value;
+            }
+          }
+
+          // Service doesn't support not specifying action
+          if (action == null) {
+            permission += "->action=" + Action.ALL;
+          }
+          LOGGER.info(dryRunMessage(importPolicy) + "Adding permission: " + permission + " to role: " + roleName.toLowerCase(Locale.US));
+          if (importPolicy) {
+            client.grantPrivilege(requestorName, roleName, component, converter.fromString(permission));
+          }
+        }
+      }
+    }
+  }
+
+  private void validatePolicy(ProviderBackend backend) throws Exception {
+    try {
+      backend.validatePolicy(true);
+    } catch (SentryConfigurationException e) {
+      printConfigErrorsWarnings(e);
+      throw e;
+    }
+  }
+
+  private void printConfigErrorsWarnings(SentryConfigurationException configException) {
+    System.out.println(" *** Found configuration problems *** ");
+    for (String errMsg : configException.getConfigErrors()) {
+      System.out.println("ERROR: " + errMsg);
+    }
+    for (String warnMsg : configException.getConfigWarnings()) {
+      System.out.println("Warning: " + warnMsg);
+    }
+  }
+
+  private void checkCompat(SimpleFileProviderBackend backend) throws Exception {
+    Map<String, Set<String>> rolesCaseMapping = new HashMap<String, Set<String>>();
+    Table<String, String, Set<String>> groupRolePrivilegeTable =
+      backend.getGroupRolePrivilegeTable();
+
+    for (String roleName : groupRolePrivilegeTable.columnKeySet()) {
+      String roleNameLower = roleName.toLowerCase(Locale.US);
+      if (!roleName.equals(roleNameLower)) {
+        if (!rolesCaseMapping.containsKey(roleNameLower)) {
+          rolesCaseMapping.put(roleNameLower, Sets.newHashSet(roleName));
+        } else {
+          rolesCaseMapping.get(roleNameLower).add(roleName);
+        }
+      }
+    }
+
+    List<String> errors = new LinkedList<String>();
+    StringBuilder warningString = new StringBuilder();
+    if (!rolesCaseMapping.isEmpty()) {
+      warningString.append("The following roles names will be lower cased when added to the Sentry Service.\n");
+      warningString.append("This will cause document-level security to fail to match the role tokens.\n");
+      warningString.append("Role names: ");
+    }
+    boolean firstWarning = true;
+
+    for (Map.Entry<String, Set<String>> entry : rolesCaseMapping.entrySet()) {
+      Set<String> caseMapping = entry.getValue();
+      if (caseMapping.size() > 1) {
+        StringBuilder errorString = new StringBuilder();
+        errorString.append("The following (cased) roles map to the same role in the sentry service: ");
+        boolean first = true;
+        for (String casedRole : caseMapping) {
+          errorString.append(first ? "" : ", ");
+          errorString.append(casedRole);
+          first = false;
+        }
+        errorString.append(".  Role in service: ").append(entry.getKey());
+        errors.add(errorString.toString());
+      }
+
+      for (String casedRole : caseMapping) {
+        warningString.append(firstWarning? "" : ", ");
+        warningString.append(casedRole);
+        firstWarning = false;
+      }
+    }
+
+    for (String error : errors) {
+      System.out.println("ERROR: " + error);
+    }
+    System.out.println("\n");
+
+    System.out.println("Warning: " + warningString.toString());
+    if (errors.size() > 0) {
+      SentryConfigurationException ex =
+          new SentryConfigurationException("Compatibility check failure");
+      ex.setConfigErrors(errors);
+      ex.setConfigWarnings(Lists.<String>asList(warningString.toString(), new String[0]));
+      throw ex;
+    }
+  }
+
+  private String dryRunMessage(boolean importPolicy) {
+    if (importPolicy) {
+      return "";
+    } else {
+      return "[Dry Run] ";
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    SentryConfigToolSolr solrTool = new SentryConfigToolSolr();
+    try {
+      solrTool.executeConfigTool(args);
+    } catch (Exception e) {
+      LOGGER.error(e.getMessage(), e);
+      Throwable current = e;
+      // find the first printable message;
+      while (current != null && current.getMessage() == null) {
+        current = current.getCause();
+      }
+      String error = "";
+      if (current != null && current.getMessage() != null) {
+        error = "Message: " + current.getMessage();
+      }
+      System.out.println("The operation failed. " + error);
+      System.exit(1);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/sentry/blob/6752f14a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaHelper.java
----------------------------------------------------------------------
diff --git a/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaHelper.java b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaHelper.java
new file mode 100644
index 0000000..3723fd9
--- /dev/null
+++ b/sentry-tools/src/main/java/org/apache/sentry/cli/tools/SentrySchemaHelper.java
@@ -0,0 +1,315 @@
+/**
+ * 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.sentry.cli.tools;
+
+import java.util.IllegalFormatException;
+
+public final class SentrySchemaHelper {
+  public static final String DB_DERBY = "derby";
+  public static final String DB_MYSQL = "mysql";
+  public static final String DB_POSTGRACE = "postgres";
+  public static final String DB_ORACLE = "oracle";
+  public static final String DB_DB2 = "db2";
+
+  public interface NestedScriptParser {
+
+    public enum CommandType {
+      PARTIAL_STATEMENT,
+      TERMINATED_STATEMENT,
+      COMMENT
+    }
+
+    String DEFAUTL_DELIMITER = ";";
+    /***
+     * Find the type of given command
+     * @param dbCommand
+     * @return
+     */
+    boolean isPartialCommand(String dbCommand) throws IllegalArgumentException;
+
+    /** Parse the DB specific nesting format and extract the inner script name if any
+     * @param dbCommand command from parent script
+     * @return
+     * @throws IllegalFormatException
+     */
+    String getScriptName(String dbCommand) throws IllegalArgumentException;
+
+    /***
+     * Find if the given command is a nested script execution
+     * @param dbCommand
+     * @return
+     */
+    boolean isNestedScript(String dbCommand);
+
+    /***
+     * Find if the given command is should be passed to DB
+     * @param dbCommand
+     * @return
+     */
+    boolean isNonExecCommand(String dbCommand);
+
+    /***
+     * Get the SQL statement delimiter
+     * @return
+     */
+    String getDelimiter();
+
+    /***
+     * Clear any client specific tags
+     * @return
+     */
+    String cleanseCommand(String dbCommand);
+
+    /***
+     * Does the DB required table/column names quoted
+     * @return
+     */
+    boolean needsQuotedIdentifier();
+
+    /***
+     * Set DB specific options if any
+     * @param dbOps
+     */
+    void setDbOpts(String dbOps);
+  }
+
+
+  /***
+   * Base implemenation of NestedScriptParser
+   * abstractCommandParser.
+   *
+   */
+  private static abstract class AbstractCommandParser implements NestedScriptParser {
+    private String dbOpts = null;
+
+    @Override
+    public boolean isPartialCommand(String dbCommand) throws IllegalArgumentException{
+      if (dbCommand == null || dbCommand.isEmpty()) {
+        throw new IllegalArgumentException("invalid command line " + dbCommand);
+      }
+      String trimmedDbCommand = dbCommand.trim();
+      return !(trimmedDbCommand.endsWith(getDelimiter()) || isNonExecCommand(trimmedDbCommand));
+    }
+
+    @Override
+    public boolean isNonExecCommand(String dbCommand) {
+      return dbCommand.startsWith("--") || dbCommand.startsWith("#");
+    }
+
+    @Override
+    public String getDelimiter() {
+      return DEFAUTL_DELIMITER;
+    }
+
+    @Override
+    public String cleanseCommand(String dbCommand) {
+      // strip off the delimiter
+      if (dbCommand.endsWith(getDelimiter())) {
+        dbCommand = dbCommand.substring(0,
+            dbCommand.length() - getDelimiter().length());
+      }
+      return dbCommand;
+    }
+
+    @Override
+    public boolean needsQuotedIdentifier() {
+      return false;
+    }
+
+    @Override
+    public void setDbOpts(String dbOpts) {
+      this.dbOpts = dbOpts;
+    }
+
+    protected String getDbOpts() {
+      return dbOpts;
+    }
+  }
+
+
+  // Derby commandline parser
+  public static class DerbyCommandParser extends AbstractCommandParser {
+    private static final String DERBY_NESTING_TOKEN = "RUN";
+
+    @Override
+    public String getScriptName(String dbCommand) throws IllegalArgumentException {
+
+      if (!isNestedScript(dbCommand)) {
+        throw new IllegalArgumentException("Not a script format " + dbCommand);
+      }
+      String[] tokens = dbCommand.split(" ");
+      if (tokens.length != 2) {
+        throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
+      }
+      return tokens[1].replace(";", "").replaceAll("'", "");
+    }
+
+    @Override
+    public boolean isNestedScript(String dbCommand) {
+      // Derby script format is RUN '<file>'
+     return dbCommand.startsWith(DERBY_NESTING_TOKEN);
+    }
+  }
+
+
+  // MySQL parser
+  public static class MySqlCommandParser extends AbstractCommandParser {
+    private static final String MYSQL_NESTING_TOKEN = "SOURCE";
+    private static final String DELIMITER_TOKEN = "DELIMITER";
+    private String delimiter = DEFAUTL_DELIMITER;
+
+    @Override
+    public boolean isPartialCommand(String dbCommand) throws IllegalArgumentException{
+      boolean isPartial = super.isPartialCommand(dbCommand);
+      // if this is a delimiter directive, reset our delimiter
+      if (dbCommand.startsWith(DELIMITER_TOKEN)) {
+        String[] tokens = dbCommand.split(" ");
+        if (tokens.length != 2) {
+          throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
+        }
+        delimiter = tokens[1];
+      }
+      return isPartial;
+    }
+
+    @Override
+    public String getScriptName(String dbCommand) throws IllegalArgumentException {
+      String[] tokens = dbCommand.split(" ");
+      if (tokens.length != 2) {
+        throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
+      }
+      // remove ending ';'
+      return tokens[1].replace(";", "");
+    }
+
+    @Override
+    public boolean isNestedScript(String dbCommand) {
+      return dbCommand.startsWith(MYSQL_NESTING_TOKEN);
+    }
+
+    @Override
+    public String getDelimiter() {
+      return delimiter;
+    }
+
+    @Override
+    public boolean isNonExecCommand(String dbCommand) {
+      return super.isNonExecCommand(dbCommand) ||
+          dbCommand.startsWith("/*") && dbCommand.endsWith("*/") ||
+          dbCommand.startsWith(DELIMITER_TOKEN);
+    }
+
+    @Override
+    public String cleanseCommand(String dbCommand) {
+      return super.cleanseCommand(dbCommand).replaceAll("/\\*.*?\\*/[^;]", "");
+    }
+
+  }
+
+  // Postgres specific parser
+  public static class PostgresCommandParser extends AbstractCommandParser {
+    public static final String POSTGRES_STRING_COMMAND_FILTER = "SET standard_conforming_strings";
+    public static final String POSTGRES_STRING_CLIENT_ENCODING = "SET client_encoding";
+    public static final String POSTGRES_SKIP_STANDARD_STRING = "postgres.filter.81";
+    private static final String POSTGRES_NESTING_TOKEN = "\\i";
+
+    @Override
+    public String getScriptName(String dbCommand) throws IllegalArgumentException {
+      String[] tokens = dbCommand.split(" ");
+      if (tokens.length != 2) {
+        throw new IllegalArgumentException("Couldn't parse line " + dbCommand);
+      }
+      // remove ending ';'
+      return tokens[1].replace(";", "");
+    }
+
+    @Override
+    public boolean isNestedScript(String dbCommand) {
+      return dbCommand.startsWith(POSTGRES_NESTING_TOKEN);
+    }
+
+    @Override
+    public boolean needsQuotedIdentifier() {
+      return true;
+    }
+
+    @Override
+    public boolean isNonExecCommand(String dbCommand) {
+      // Skip "standard_conforming_strings" command which is not supported in older postgres
+      if (POSTGRES_SKIP_STANDARD_STRING.equalsIgnoreCase(getDbOpts()) 
+        && (dbCommand.startsWith(POSTGRES_STRING_COMMAND_FILTER) || dbCommand.startsWith(POSTGRES_STRING_CLIENT_ENCODING))) {
+        return true;
+      }
+      return super.isNonExecCommand(dbCommand);
+    }
+  }
+
+  //Oracle specific parser
+  public static class OracleCommandParser extends AbstractCommandParser {
+    private static final String ORACLE_NESTING_TOKEN = "@";
+    @Override
+    public String getScriptName(String dbCommand) throws IllegalArgumentException {
+      if (!isNestedScript(dbCommand)) {
+        throw new IllegalArgumentException("Not a nested script format " + dbCommand);
+      }
+      // remove ending ';' and starting '@'
+      return dbCommand.replace(";", "").replace(ORACLE_NESTING_TOKEN, "");
+    }
+
+    @Override
+    public boolean isNestedScript(String dbCommand) {
+      return dbCommand.startsWith(ORACLE_NESTING_TOKEN);
+    }
+  }
+
+  // DB2 commandline parser
+  public static class DB2CommandParser extends AbstractCommandParser {
+
+    @Override
+    public String getScriptName(String dbCommand) throws IllegalArgumentException {
+        //DB2 does not support nesting script
+        throw new IllegalArgumentException("DB2 does not support nesting script " + dbCommand);
+    }
+
+    @Override
+    public boolean isNestedScript(String dbCommand) {
+        //DB2 does not support nesting script
+     return false;
+    }
+  }
+
+  public static NestedScriptParser getDbCommandParser(String dbName) {
+    if (dbName.equalsIgnoreCase(DB_DERBY)) {
+      return new DerbyCommandParser();
+    } else if (dbName.equalsIgnoreCase(DB_MYSQL)) {
+      return new MySqlCommandParser();
+    } else if (dbName.equalsIgnoreCase(DB_POSTGRACE)) {
+      return new PostgresCommandParser();
+    } else if (dbName.equalsIgnoreCase(DB_ORACLE)) {
+        return new OracleCommandParser();
+    } else if (dbName.equalsIgnoreCase(DB_DB2)) {
+      return new DB2CommandParser();
+    } else {
+      throw new IllegalArgumentException("Unknown dbType " + dbName);
+    }
+  }
+  
+  private SentrySchemaHelper() {
+    // Make constructor private to avoid instantiation
+  }
+}