Repository: incubator-hawq Updated Branches: refs/heads/1485 [created] 0580d0902
HAWQ-1485. Use user/password instead of credentials cache in Ranger lookup for HAWQ with Kerberos enabled. Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/0580d090 Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/0580d090 Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/0580d090 Branch: refs/heads/1485 Commit: 0580d09021f6fea41c1de7c1b5c6477bf90b3aa7 Parents: 444a73a Author: interma <[email protected]> Authored: Tue Jun 13 12:09:40 2017 +0800 Committer: Wen Lin <[email protected]> Committed: Wed Jun 14 15:34:05 2017 +0800 ---------------------------------------------------------------------- .../apache/hawq/ranger/service/HawqClient.java | 235 +++++++------------ .../hawq/ranger/service/HawqResourceMgr.java | 191 ++++++++------- .../hawq/ranger/service/RangerServiceHawq.java | 80 +++++-- .../hawq/ranger/service/HawqClientTest.java | 23 +- .../ranger/service/RangerServiceHawqTest.java | 24 +- 5 files changed, 255 insertions(+), 298 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/0580d090/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqClient.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqClient.java b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqClient.java index 5d2cd71..bae2d2d 100644 --- a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqClient.java +++ b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqClient.java @@ -22,6 +22,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hawq.ranger.model.HawqProtocols; import org.apache.ranger.plugin.client.BaseClient; + import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.sql.Connection; @@ -74,11 +75,7 @@ public class HawqClient extends BaseClient { private static final String DEFAULT_DATABASE_TEMPLATE = "DBTOBEREPLACEDINJDBCURL"; private static final String JDBC_DRIVER_CLASS = "org.postgresql.Driver"; - private boolean isKerberosAuth = false; - private Connection con; - private String jdbc_url_template = ""; - private Map<String, String> connectionProperties; - + // we need to load class for the Postgres Driver directly to allow it to register with DriverManager // since DriverManager's classloader will not be able to find it by itself due to plugin's special classloaders static { @@ -91,125 +88,60 @@ public class HawqClient extends BaseClient { } public HawqClient(String serviceName, Map<String, String> connectionProperties) throws Exception { - super(serviceName,connectionProperties); + super(serviceName, connectionProperties); this.connectionProperties = connectionProperties; - initHawq(); } - - public void initHawq() throws Exception { - if(connectionProperties.containsKey(AUTHENTICATION)) { - isKerberosAuth = connectionProperties.get(AUTHENTICATION).equals(KERBEROS); - } - if (isKerberosAuth) { - LOG.info("Secured Mode: JDBC Connection done with preAuthenticated Subject"); - - // do kinit in hawqclient by principal name and password - final String userName = getConfigHolder().getUserName(); - final String password = getConfigHolder().getPassword(); - - String[] kinitcmd ={ - "/bin/sh", - "-c", - "echo '"+password+"' | kinit " + userName - }; - java.lang.Runtime rt = java.lang.Runtime.getRuntime(); - if (LOG.isDebugEnabled()) { - LOG.debug("kinit command: "+"echo '"+password+"' | kinit " + userName); - } - java.lang.Process p = rt.exec(kinitcmd); - - Subject.doAs(getLoginSubject(), new PrivilegedExceptionAction<Void>(){ - public Void run() throws Exception { - final String lookupPricipalName = getConfigHolder().getUserName(); - final String serverprincipal = connectionProperties.get("principal"); - initConnectionKerberos(serverprincipal, lookupPricipalName); - return null; - }}); - } - else { - LOG.info("Trying to use UnSecure client with username "+ getConfigHolder().getUserName() +" and password"); - final String userName = getConfigHolder().getUserName(); - final String password = getConfigHolder().getPassword(); - initConnection(userName, password); - } - } - - private void initConnectionKerberos(String serverPricipal, String userPrincipal) throws SQLException{ - try { - String url = String.format("jdbc:postgresql://%s:%s/%s?kerberosServerName=%s&jaasApplicationName=pgjdbc&user=%s", - connectionProperties.get("hostname"), - connectionProperties.get("port"), DEFAULT_DATABASE, - serverPricipal, userPrincipal - ); - if (LOG.isDebugEnabled()) { - LOG.debug("InitConnectionKerberos "+ url); - } - con = DriverManager.getConnection(url); - jdbc_url_template = String.format("jdbc:postgresql://%s:%s/%s?kerberosServerName=%s&jaasApplicationName=pgjdbc&user=%s", - connectionProperties.get("hostname"), - connectionProperties.get("port"), DEFAULT_DATABASE_TEMPLATE, - serverPricipal, userPrincipal - ); - } catch (SQLException e) { - e.printStackTrace(); - LOG.error("Unable to Connect to Hawq", e); - throw e; - } catch (SecurityException se) { - se.printStackTrace(); - } - } - - - private void initConnection(String userName, String password) throws SQLException { - try { - String url = String.format("jdbc:postgresql://%s:%s/%s", connectionProperties.get("hostname"), connectionProperties.get("port"), DEFAULT_DATABASE); - if (LOG.isDebugEnabled()) { - LOG.debug("InitConnectionKerberos "+ url); - } - con = DriverManager.getConnection(url, userName, password); - jdbc_url_template = String.format("jdbc:postgresql://%s:%s/%s", connectionProperties.get("hostname"), connectionProperties.get("port"), DEFAULT_DATABASE_TEMPLATE); - } catch (SQLException e) { - e.printStackTrace(); - LOG.error("Unable to Connect to Hawq", e); - throw e; - } catch (SecurityException se) { - se.printStackTrace(); - } - } - - public void setConnection(Connection conn) { - con = conn; - } - - public void resetConnection(String db) throws SQLException{ - try { - if(db == null) { - return; - } - String newdb = db; - LOG.debug("resetconnectionbefore "+ jdbc_url_template + newdb); - String url = jdbc_url_template.replace(DEFAULT_DATABASE_TEMPLATE, newdb); - if (LOG.isDebugEnabled()) { - LOG.debug("resetconnection "+ jdbc_url_template+ url); - } - if(con !=null && !con.isClosed()){ - con.close(); - } - if (isKerberosAuth) { - con = DriverManager.getConnection(url); - } else { - final String userName = getConfigHolder().getUserName(); - final String password = getConfigHolder().getPassword(); - con = DriverManager.getConnection(url, userName, password); - } - } catch (SQLException e) { - e.printStackTrace(); - LOG.error("Unable to Connect to Hawq", e); - throw e; - } catch (SecurityException se) { - se.printStackTrace(); - } - } + + /** + * clone a new Properties for debug logging: + * 1. remove password field for preventing plain password leak in log + * 2. add a _password_length field for debug + * + * @param connectionProperties + * @return a new cloned Map for debug logging + */ + private Map<String, String> removePassword(Map<String, String> connectionProperties) { + Map<String, String> new_property = new HashMap<String, String>(connectionProperties); + if (new_property.containsKey("password")) { + String password = new_property.get("password"); + new_property.remove("password"); + new_property.put("_password_length", Integer.toString(password.length())); + } + return new_property; + } + + private Connection getConnection(Map<String, String> connectionProperties) throws SQLException { + return getConnection(connectionProperties, null); + } + + private Connection getConnection(Map<String, String> connectionProperties, String database) throws SQLException { + + String db = database != null ? database : DEFAULT_DATABASE; + Properties props = new Properties(); + + if (LOG.isDebugEnabled()) { + Map<String, String> debugProperties = removePassword(connectionProperties); + LOG.debug("<== HawqClient.checkConnection configuration" + debugProperties ); + } + + if (connectionProperties.containsKey(AUTHENTICATION) && connectionProperties.get(AUTHENTICATION).equals(KERBEROS)) { + //kerberos mode + props.setProperty("kerberosServerName", connectionProperties.get("principal")); + props.setProperty("jaasApplicationName", "pgjdbc"); + } + + + String url = String.format("jdbc:postgresql://%s:%s/%s", connectionProperties.get("hostname"), connectionProperties.get("port"), db); + props.setProperty("user", connectionProperties.get("username")); + props.setProperty("password", connectionProperties.get("password")); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== HawqClient.checkConnection Connecting to: (" + url + ") with user: " + connectionProperties.get("username")); + } + + return DriverManager.getConnection(url, props); + } + /** * Uses the connectionProperties and attempts to connect to Hawq. @@ -230,8 +162,10 @@ public class HawqClient extends BaseClient { LOG.debug("<== HawqClient.checkConnection Starting connection to hawq"); } + Connection conn = null; try { - if(con.getCatalog() != null) { + conn = getConnection(connectionProperties); + if (conn.getCatalog() != null) { isConnected = true; description = CONNECTION_SUCCESSFUL_MESSAGE; } @@ -239,11 +173,12 @@ public class HawqClient extends BaseClient { LOG.error("<== HawqClient.checkConnection Error: Failed to connect" + e); description = e.getMessage(); } finally { + closeConnection(conn); } String message = isConnected ? CONNECTION_SUCCESSFUL_MESSAGE : CONNECTION_FAILURE_MESSAGE; - generateResponseDataMap(isConnected, message, description, null, null, result); + return result; } @@ -258,7 +193,7 @@ public class HawqClient extends BaseClient { public List<String> getProtocolList(String userInput) throws SQLException { Set<String> allProtocols = new HashSet<>(); for (String protocol : INTERNAL_PROTOCOLS) { - if(protocol.startsWith(userInput) || userInput.equals(WILDCARD)) { + if (protocol.startsWith(userInput) || userInput.equals(WILDCARD)) { allProtocols.add(protocol); } } @@ -270,7 +205,7 @@ public class HawqClient extends BaseClient { return queryHawqPerDb(userInput, resources.get("database"), SCHEMA_NAME, SCHEMA_LIST_QUERY); } - public List<String> getLanguageList(String userInput, Map<String, List<String>> resources) throws SQLException { + public List<String> getLanguageList(String userInput, Map<String, List<String>> resources) throws SQLException { return queryHawqPerDb(userInput, resources.get("database"), LANGUAGE_NAME, LANGUAGE_LIST_QUERY); } @@ -307,31 +242,30 @@ public class HawqClient extends BaseClient { PreparedStatement preparedStatement = null; ResultSet resultSet = null; + Connection conn = null; if (databases.contains(WILDCARD)) { databases = getDatabaseList(WILDCARD); } - if(con == null) { - return new ArrayList<>(uniqueResults); - } - for (String db: databases) { - resetConnection(db); + for (String db : databases) { + if (LOG.isDebugEnabled()) { LOG.debug("<== HawqClient.queryHawqPerDbAndSchema: Connecting to db: " + db); } try { - preparedStatement = handleWildcardPreparedStatement(userInput, query, con); - + conn = getConnection(connectionProperties, db); + preparedStatement = handleWildcardPreparedStatement(userInput, query, conn); + if (LOG.isDebugEnabled()) { LOG.debug("<== HawqClient.queryHawqPerDbAndSchema Starting query: " + preparedStatement.toString()); } - + resultSet = preparedStatement.executeQuery(); - while(resultSet.next()) { - if(schemas.contains(resultSet.getString(schemaColumnName)) || schemas.contains(WILDCARD)) { - uniqueResults.add(resultSet.getString(resultColumnName)); + while (resultSet.next()) { + if (schemas.contains(resultSet.getString(schemaColumnName)) || schemas.contains(WILDCARD)) { + uniqueResults.add(resultSet.getString(resultColumnName)); } } @@ -344,23 +278,22 @@ public class HawqClient extends BaseClient { } finally { closeResultSet(resultSet); closeStatement(preparedStatement); + closeConnection(conn); } + } return new ArrayList<>(uniqueResults); } - private List<String> queryHawq(String userInput, String columnName, String query, String database) throws SQLException{ + private List<String> queryHawq(String userInput, String columnName, String query, String database) throws SQLException { List<String> result = new ArrayList<>(); PreparedStatement preparedStatement = null; ResultSet resultSet = null; + Connection conn = null; try { - resetConnection(database); - if(con == null) { - return result; - } - - preparedStatement = handleWildcardPreparedStatement(userInput, query, con); + conn = getConnection(connectionProperties, database); + preparedStatement = handleWildcardPreparedStatement(userInput, query, conn); if (LOG.isDebugEnabled()) { LOG.debug("<== HawqClient.queryHawq Starting query: " + preparedStatement.toString()); @@ -368,7 +301,7 @@ public class HawqClient extends BaseClient { resultSet = preparedStatement.executeQuery(); - while(resultSet.next()) { + while (resultSet.next()) { result.add(resultSet.getString(columnName)); } @@ -382,6 +315,7 @@ public class HawqClient extends BaseClient { } finally { closeResultSet(resultSet); closeStatement(preparedStatement); + closeConnection(conn); } return result; @@ -412,20 +346,11 @@ public class HawqClient extends BaseClient { private void closeConnection(Connection conn) { try { if (conn != null) { - conn.close(); + conn.close(); } } catch (Exception e) { // ignore } } - - public void close() { - Subject.doAs(getLoginSubject(), new PrivilegedAction<Void>(){ - public Void run() { - closeConnection(con); - return null; - } - }); - } } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/0580d090/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqResourceMgr.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqResourceMgr.java b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqResourceMgr.java index 6dc9cad..a90261d 100644 --- a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqResourceMgr.java +++ b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/HawqResourceMgr.java @@ -32,111 +32,104 @@ import java.util.Collections; public abstract class HawqResourceMgr { - private static final Logger LOG = Logger.getLogger(HawqResourceMgr.class); - + private static final Logger LOG = Logger.getLogger(HawqResourceMgr.class); + public static List<String> getHawqResources(String serviceName, String serviceType, Map<String, String> configs, ResourceLookupContext context) throws Exception { - final String userInput = context.getUserInput(); + final String userInput = context.getUserInput(); HawqResource hawqResource = HawqResource.valueOf(context.getResourceName().toUpperCase()); final Map<String, List<String>> resources = context.getResources(); - + List<String> result = null; if (serviceName != null && userInput != null) { - try { - - if(LOG.isDebugEnabled()) { - LOG.debug("==> HawqResourceMgr.getHawqResources() UserInput: "+ userInput + " configs: " + configs); - } - final HawqClient hawqClient =new HawqClient(serviceName, configs); - Callable<List<String>> callableObj = null; - - if(hawqClient != null) { - switch (hawqResource) { - case DATABASE: - callableObj = new Callable<List<String>>() { - @Override - public List<String> call() throws SQLException{ - return hawqClient.getDatabaseList(userInput); - } - }; - break; - case TABLESPACE: - callableObj = new Callable<List<String>>() { - @Override - public List<String> call() throws SQLException{ - return hawqClient.getTablespaceList(userInput); - } - }; - break; - case PROTOCOL: - callableObj = new Callable<List<String>>() { - @Override - public List<String> call() throws SQLException{ - return hawqClient.getProtocolList(userInput); - } - }; - break; - case SCHEMA: - callableObj = new Callable<List<String>>() { - @Override - public List<String> call() throws SQLException{ - return hawqClient.getSchemaList(userInput, resources); - } - }; - break; - case LANGUAGE: - callableObj = new Callable<List<String>>() { - @Override - public List<String> call() throws SQLException{ - return hawqClient.getLanguageList(userInput, resources); - } - }; - break; - case TABLE: - callableObj = new Callable<List<String>>() { - @Override - public List<String> call() throws SQLException{ - return hawqClient.getTableList(userInput, resources); - } - }; - break; - case SEQUENCE: - callableObj = new Callable<List<String>>() { - @Override - public List<String> call() throws SQLException { - return hawqClient.getSequenceList(userInput, resources); - } - }; - break; - case FUNCTION: - callableObj = new Callable<List<String>>() { - @Override - public List<String> call() throws SQLException{ - return hawqClient.getFunctionList(userInput, resources); - } - }; - break; - default: - throw new IllegalArgumentException("Resource requested does not exist."); - } - } - - if (callableObj != null) { - synchronized (hawqClient) { - result = TimedEventUtil.timedTask(callableObj, 5, - TimeUnit.SECONDS); - } - } else { - LOG.error("Could not initiate at timedTask"); - } - - - Collections.sort(result); - hawqClient.close(); - } catch (Exception e) { - LOG.error("Unable to get hive resources.", e); - throw e; - } + try { + + if (LOG.isDebugEnabled()) { + LOG.debug("==> HawqResourceMgr.getHawqResources() UserInput: " + userInput); + } + final HawqClient hawqClient = new HawqClient(serviceName, configs); + Callable<List<String>> callableObj; + + switch (hawqResource) { + case DATABASE: + callableObj = new Callable<List<String>>() { + @Override + public List<String> call() throws SQLException { + return hawqClient.getDatabaseList(userInput); + } + }; + break; + case TABLESPACE: + callableObj = new Callable<List<String>>() { + @Override + public List<String> call() throws SQLException { + return hawqClient.getTablespaceList(userInput); + } + }; + break; + case PROTOCOL: + callableObj = new Callable<List<String>>() { + @Override + public List<String> call() throws SQLException { + return hawqClient.getProtocolList(userInput); + } + }; + break; + case SCHEMA: + callableObj = new Callable<List<String>>() { + @Override + public List<String> call() throws SQLException { + return hawqClient.getSchemaList(userInput, resources); + } + }; + break; + case LANGUAGE: + callableObj = new Callable<List<String>>() { + @Override + public List<String> call() throws SQLException { + return hawqClient.getLanguageList(userInput, resources); + } + }; + break; + case TABLE: + callableObj = new Callable<List<String>>() { + @Override + public List<String> call() throws SQLException { + return hawqClient.getTableList(userInput, resources); + } + }; + break; + case SEQUENCE: + callableObj = new Callable<List<String>>() { + @Override + public List<String> call() throws SQLException { + return hawqClient.getSequenceList(userInput, resources); + } + }; + break; + case FUNCTION: + callableObj = new Callable<List<String>>() { + @Override + public List<String> call() throws SQLException { + return hawqClient.getFunctionList(userInput, resources); + } + }; + break; + default: + throw new IllegalArgumentException("Resource requested does not exist."); + } + + synchronized (hawqClient) { + result = TimedEventUtil.timedTask(callableObj, 5, + TimeUnit.SECONDS); + } + + + Collections.sort(result); + } catch (Exception e) { + LOG.error("Unable to get Hawq resources.", e); + throw e; + } } return result; } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/0580d090/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/RangerServiceHawq.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/RangerServiceHawq.java b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/RangerServiceHawq.java index 9c1ccc8..967924a 100644 --- a/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/RangerServiceHawq.java +++ b/ranger-plugin/admin-plugin/src/main/java/org/apache/hawq/ranger/service/RangerServiceHawq.java @@ -25,6 +25,7 @@ import org.apache.ranger.plugin.service.RangerBaseService; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ranger.plugin.service.ResourceLookupContext; +import org.apache.ranger.plugin.util.PasswordUtils; import java.util.*; @@ -33,33 +34,38 @@ public class RangerServiceHawq extends RangerBaseService { private static final Log LOG = LogFactory.getLog(RangerServiceHawq.class); public RangerServiceHawq() { - super(); - } - - @Override - public void init(RangerServiceDef serviceDef, RangerService service) { - super.init(serviceDef, service); - } - + super(); + } + + @Override + public void init(RangerServiceDef serviceDef, RangerService service) { + super.init(serviceDef, service); + } + @Override public HashMap<String, Object> validateConfig() throws Exception { boolean isDebugEnabled = LOG.isDebugEnabled(); - if(isDebugEnabled) { + if (isDebugEnabled) { LOG.debug("==> RangerServiceHawq.validateConfig Service: (hawq)"); } HashMap<String, Object> result = new HashMap<>(); - String serviceName = getServiceName(); if (configs != null) { - try { - HawqClient hawqClient = new HawqClient(serviceName, configs); - result = hawqClient.checkConnection(configs); - hawqClient.close(); - } catch (HadoopException e) { - LOG.error("<== RangerServiceHawq.validateConfig Error:" + e); - throw e; + boolean retry = false; + + // try normal password (user input in RangerUI form) + result = checkConnection(configs); + if (result.containsKey("connectivityStatus") && !(boolean)(result.get("connectivityStatus"))) { + retry = true; + } + + if (retry) { + // try decrypt password + decryptPassword(configs); + result = checkConnection(configs); } + } if (isDebugEnabled) { @@ -70,12 +76,44 @@ public class RangerServiceHawq extends RangerBaseService { @Override public List<String> lookupResource(ResourceLookupContext context) throws Exception { - String serviceName = getServiceName(); - String serviceType = getServiceType(); - - List<String> resources = HawqResourceMgr.getHawqResources(serviceName, serviceType, getConfigs(), context); + String serviceName = getServiceName(); + String serviceType = getServiceType(); + + // lookup always need decrypt password (fetch from database) + decryptPassword(configs); + + List<String> resources = HawqResourceMgr.getHawqResources(serviceName, serviceType, configs, context); return resources; } + private HashMap<String, Object> checkConnection(Map<String, String> configs) throws Exception { + HashMap<String, Object> result; + String serviceName = getServiceName(); + + try { + HawqClient hawqClient = new HawqClient(serviceName, configs); + result = hawqClient.checkConnection(configs); + } catch (HadoopException e) { + LOG.error("<== RangerServiceHawq.validateConfig Error:" + e); + throw e; + } + + return result; + } + + private void decryptPassword(Map<String, String> configs) throws Exception { + if (configs.containsKey("password")) { + String normal_password = configs.get("password"); + try { + normal_password = PasswordUtils.decryptPassword(normal_password); + } + catch (java.io.IOException e) { + // when decrypt failed do nothing + LOG.warn("decrypt_password failed: " + e); + } + configs.put("password", normal_password); + } + } + } http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/0580d090/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/HawqClientTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/HawqClientTest.java b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/HawqClientTest.java index be3be17..9b288f9 100644 --- a/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/HawqClientTest.java +++ b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/HawqClientTest.java @@ -27,20 +27,23 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import java.sql.Connection; +import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import java.util.List; import java.util.Arrays; import java.util.Collections; import static org.apache.hawq.ranger.service.HawqClient.*; import static org.junit.Assert.*; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyMap; +import static org.mockito.Matchers.anyString; import static org.powermock.api.mockito.PowerMockito.*; -import static org.powermock.api.support.membermodification.MemberMatcher.method; -import static org.powermock.api.support.membermodification.MemberModifier.suppress; @RunWith(PowerMockRunner.class) @PrepareForTest(HawqClient.class) @@ -68,11 +71,10 @@ public class HawqClientTest { connectionProperties.put("username", "username"); connectionProperties.put("password", "password"); + mockStatic(DriverManager.class); suppress(constructor(BaseClient.class, String.class, Map.class)); - suppress(method(HawqClient.class, "initHawq")); - suppress(method(HawqClient.class, "resetConnection")); hawqClient = new HawqClient("hawq", connectionProperties); - hawqClient.setConnection(conn); + hawqClientSpy = PowerMockito.spy(hawqClient); resources = new HashMap<>(); @@ -84,6 +86,7 @@ public class HawqClientTest { @Test public void testCheckConnection_Failure() throws Exception { + when(DriverManager.getConnection(anyString(), any(Properties.class))).thenReturn(conn); when(conn.getCatalog()).thenReturn(null); Map<String, Object> response = hawqClient.checkConnection(connectionProperties); assertEquals(CONNECTION_FAILURE_MESSAGE, response.get("message")); @@ -92,6 +95,7 @@ public class HawqClientTest { @Test public void testCheckConnection_Success() throws Exception { + when(DriverManager.getConnection(anyString(), any(Properties.class))).thenReturn(conn); when(conn.getCatalog()).thenReturn("catalog"); Map<String, Object> response = hawqClient.checkConnection(connectionProperties); assertEquals(CONNECTION_SUCCESSFUL_MESSAGE, response.get("message")); @@ -100,8 +104,8 @@ public class HawqClientTest { @Test public void testCheckConnection_ThrowsSQLException_Failure() throws Exception { - when(conn.getCatalog()).thenThrow(new SQLException("Failed to connect")); - Map<String, Object> response = hawqClient.checkConnection(connectionProperties); + when(DriverManager.getConnection(anyString(), any(Properties.class))).thenThrow(new SQLException("Failed to connect")); + Map<String, Object> response = hawqClient.checkConnection(connectionProperties); assertEquals(CONNECTION_FAILURE_MESSAGE, response.get("message")); assertEquals("Failed to connect", response.get("description")); assertFalse((Boolean) response.get("connectivityStatus")); @@ -113,6 +117,7 @@ public class HawqClientTest { when(preparedStatement.executeQuery()).thenReturn(resultSet); when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false); when(resultSet.getString(DATNAME)).thenReturn("db1").thenReturn("db2"); + PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString()); assertEquals(Arrays.asList("db1", "db2"), hawqClientSpy.getDatabaseList("d")); } @@ -163,6 +168,7 @@ public class HawqClientTest { @Test public void testTableList_Success() throws Exception { + PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString()); when(conn.prepareStatement(TABLE_LIST_QUERY)).thenReturn(preparedStatement); when(preparedStatement.executeQuery()).thenReturn(resultSet); when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false); @@ -175,6 +181,7 @@ public class HawqClientTest { @Test public void testSequenceList_Success() throws Exception { + PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString()); when(conn.prepareStatement(SEQUENCE_LIST_QUERY)).thenReturn(preparedStatement); when(preparedStatement.executeQuery()).thenReturn(resultSet); when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false); @@ -187,6 +194,7 @@ public class HawqClientTest { @Test public void testSequenceList_SchemaFiltered_Success() throws Exception { + PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString()); when(conn.prepareStatement(SEQUENCE_LIST_QUERY)).thenReturn(preparedStatement); when(preparedStatement.executeQuery()).thenReturn(resultSet); when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false); @@ -197,6 +205,7 @@ public class HawqClientTest { @Test public void testFunctionList_Success() throws Exception { + PowerMockito.doReturn(conn).when(hawqClientSpy, "getConnection", anyMap(), anyString()); when(conn.prepareStatement(FUNCTION_LIST_QUERY)).thenReturn(preparedStatement); when(preparedStatement.executeQuery()).thenReturn(resultSet); when(resultSet.next()).thenReturn(true).thenReturn(true).thenReturn(false); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/0580d090/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/RangerServiceHawqTest.java ---------------------------------------------------------------------- diff --git a/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/RangerServiceHawqTest.java b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/RangerServiceHawqTest.java index 7ef3096..5264929 100644 --- a/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/RangerServiceHawqTest.java +++ b/ranger-plugin/admin-plugin/src/test/java/org/apache/hawq/ranger/service/RangerServiceHawqTest.java @@ -18,7 +18,6 @@ package org.apache.hawq.ranger.service; import org.apache.ranger.plugin.client.BaseClient; -import org.apache.hawq.ranger.service.HawqClient; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -26,25 +25,25 @@ import org.mockito.Mock; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import static org.powermock.api.mockito.PowerMockito.*; + import java.sql.Connection; import java.sql.DriverManager; import java.util.HashMap; import java.util.Map; -import static org.mockito.Matchers.*; +import java.util.Properties; -import static org.powermock.api.support.membermodification.MemberMatcher.method; import static org.apache.hawq.ranger.service.HawqClient.CONNECTION_SUCCESSFUL_MESSAGE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.powermock.api.mockito.PowerMockito.mockStatic; import static org.powermock.api.mockito.PowerMockito.when; import static org.powermock.api.support.membermodification.MemberMatcher.constructor; import static org.powermock.api.support.membermodification.MemberModifier.suppress; - @RunWith(PowerMockRunner.class) -@PrepareForTest({HawqClient.class, RangerServiceHawq.class}) +@PrepareForTest(HawqClient.class) public class RangerServiceHawqTest { private RangerServiceHawq service; @@ -54,8 +53,6 @@ public class RangerServiceHawqTest { HawqClient mockHawqClient; @Mock Connection conn; - - private Map<String, String> connectionProperties; @Before public void setup() { @@ -76,18 +73,13 @@ public class RangerServiceHawqTest { @Test public void testValidateConfigSuccess() throws Exception { - suppress(constructor(BaseClient.class, String.class, Map.class)); - suppress(method(HawqClient.class, "initHawq")); - HashMap<String, Object> result = new HashMap<>(); result.put("message", "ConnectionTest Successful"); result.put("description", "ConnectionTest Successful"); result.put("connectivityStatus", true); - - mockHawqClient = new HawqClient("hawq", connectionProperties); - mockHawqClient.setConnection(conn); - PowerMockito.whenNew(HawqClient.class).withArguments(anyObject(),anyObject()).thenReturn(mockHawqClient); - + + suppress(constructor(BaseClient.class, String.class, Map.class)); + PowerMockito.when(DriverManager.getConnection(anyString(), any(Properties.class))).thenReturn(conn); when(conn.getCatalog()).thenReturn("catalog"); HashMap<String, Object> response = service.validateConfig();
