diff --git a/external/docker-integration-tests/pom.xml b/external/docker-integration-tests/pom.xml
index 3b7bd2a71d2d2..7f9e92f585168 100644
--- a/external/docker-integration-tests/pom.xml
+++ b/external/docker-integration-tests/pom.xml
@@ -149,20 +149,19 @@
-Dmaven.repo.drivers=http://my.local.repo
2) have a copy of the DB2 JCC driver and run the following commands :
- mvn install:install-file -Dfile=${path to db2jcc4.jar} \
+ mvn install:install-file -Dfile=${path to jcc.jar} \
-DgroupId=com.ibm.db2 \
- -DartifactId=db2jcc4 \
- -Dversion=10.5 \
+ -DartifactId=jcc \
+ -Dversion=11.5 \
-Dpackaging=jar
Note: IBM DB2 JCC driver is available for download at
http://www-01.ibm.com/support/docview.wss?uid=swg21363866
-->
- com.ibm.db2.jcc
- db2jcc4
- 10.5.0.5
- jar
+ com.ibm.db2
+ jcc
+ test
com.microsoft.sqlserver
diff --git a/external/docker-integration-tests/src/test/resources/db2_krb_setup.sh b/external/docker-integration-tests/src/test/resources/db2_krb_setup.sh
new file mode 100755
index 0000000000000..c9ee25266b89b
--- /dev/null
+++ b/external/docker-integration-tests/src/test/resources/db2_krb_setup.sh
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+# 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.
+#
+
+USERPROFILE=/database/config/db2inst1/sqllib/userprofile
+echo "export DB2_KRB5_PRINCIPAL=db2/__IP_ADDRESS_REPLACE_ME__@EXAMPLE.COM" >> $USERPROFILE
+echo "export KRB5_KTNAME=/var/custom/db2.keytab" >> $USERPROFILE
+# This trick is needed because DB2 forwards environment variables automatically only if it's starting with DB2.
+su - db2inst1 -c "db2set DB2ENVLIST=KRB5_KTNAME"
+
+su - db2inst1 -c "db2 UPDATE DBM CFG USING SRVCON_GSSPLUGIN_LIST IBMkrb5 IMMEDIATE"
+su - db2inst1 -c "db2 UPDATE DBM CFG USING SRVCON_AUTH KERBEROS IMMEDIATE"
+
+su - db2inst1 -c "db2stop force; db2start"
diff --git a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2IntegrationSuite.scala b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2IntegrationSuite.scala
index 32e56f03ee521..b1379c70add71 100644
--- a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2IntegrationSuite.scala
+++ b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2IntegrationSuite.scala
@@ -27,7 +27,6 @@ import org.apache.spark.sql.Row
import org.apache.spark.sql.types.{BooleanType, ByteType, ShortType, StructType}
import org.apache.spark.tags.DockerTest
-
@DockerTest
@Ignore // AMPLab Jenkins needs to be updated before shared memory works on docker
class DB2IntegrationSuite extends DockerJDBCIntegrationSuite {
diff --git a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2KrbIntegrationSuite.scala b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2KrbIntegrationSuite.scala
new file mode 100644
index 0000000000000..1c640efa20b68
--- /dev/null
+++ b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DB2KrbIntegrationSuite.scala
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.spark.sql.jdbc
+
+import java.security.PrivilegedExceptionAction
+import java.sql.Connection
+import javax.security.auth.login.Configuration
+
+import com.spotify.docker.client.messages.{ContainerConfig, HostConfig}
+import org.apache.hadoop.security.{SecurityUtil, UserGroupInformation}
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS
+
+import org.apache.spark.sql.execution.datasources.jdbc.JDBCOptions
+import org.apache.spark.sql.execution.datasources.jdbc.connection.{DB2ConnectionProvider, SecureConnectionProvider}
+import org.apache.spark.tags.DockerTest
+
+@DockerTest
+class DB2KrbIntegrationSuite extends DockerKrbJDBCIntegrationSuite {
+ override protected val userName = s"db2/$dockerIp"
+ override protected val keytabFileName = "db2.keytab"
+
+ override val db = new DatabaseOnDocker {
+ override val imageName = "ibmcom/db2:11.5.0.0a"
+ override val env = Map(
+ "DB2INST1_PASSWORD" -> "rootpass",
+ "LICENSE" -> "accept",
+ "DBNAME" -> "db2"
+ )
+ override val usesIpc = false
+ override val jdbcPort = 50000
+ override val privileged = true
+ override def getJdbcUrl(ip: String, port: Int): String = s"jdbc:db2://$ip:$port/db2"
+ override def getJdbcProperties() = {
+ val options = new JDBCOptions(Map[String, String](
+ JDBCOptions.JDBC_URL -> getJdbcUrl(dockerIp, externalPort),
+ JDBCOptions.JDBC_TABLE_NAME -> "bar",
+ JDBCOptions.JDBC_KEYTAB -> keytabFileName,
+ JDBCOptions.JDBC_PRINCIPAL -> principal
+ ))
+ new DB2ConnectionProvider(null, options).getAdditionalProperties()
+ }
+
+ override def beforeContainerStart(
+ hostConfigBuilder: HostConfig.Builder,
+ containerConfigBuilder: ContainerConfig.Builder): Unit = {
+ copyExecutableResource("db2_krb_setup.sh", initDbDir, replaceIp)
+
+ hostConfigBuilder.appendBinds(
+ HostConfig.Bind.from(initDbDir.getAbsolutePath)
+ .to("/var/custom").readOnly(true).build()
+ )
+ }
+ }
+
+ override protected def setAuthentication(keytabFile: String, principal: String): Unit = {
+ val config = new SecureConnectionProvider.JDBCConfiguration(
+ Configuration.getConfiguration, "JaasClient", keytabFile, principal)
+ Configuration.setConfiguration(config)
+ }
+
+ override def getConnection(): Connection = {
+ val config = new org.apache.hadoop.conf.Configuration
+ SecurityUtil.setAuthenticationMethod(KERBEROS, config)
+ UserGroupInformation.setConfiguration(config)
+
+ UserGroupInformation.loginUserFromKeytabAndReturnUGI(principal, keytabFullPath).doAs(
+ new PrivilegedExceptionAction[Connection]() {
+ override def run(): Connection = {
+ DB2KrbIntegrationSuite.super.getConnection()
+ }
+ }
+ )
+ }
+}
diff --git a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DockerJDBCIntegrationSuite.scala b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DockerJDBCIntegrationSuite.scala
index 376dd4646608c..d15b366bfc9b0 100644
--- a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DockerJDBCIntegrationSuite.scala
+++ b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DockerJDBCIntegrationSuite.scala
@@ -18,7 +18,8 @@
package org.apache.spark.sql.jdbc
import java.net.ServerSocket
-import java.sql.Connection
+import java.sql.{Connection, DriverManager}
+import java.util.Properties
import scala.collection.JavaConverters._
import scala.util.control.NonFatal
@@ -53,11 +54,21 @@ abstract class DatabaseOnDocker {
*/
val jdbcPort: Int
+ /**
+ * Parameter whether the container should run privileged.
+ */
+ val privileged: Boolean = false
+
/**
* Return a JDBC URL that connects to the database running at the given IP address and port.
*/
def getJdbcUrl(ip: String, port: Int): String
+ /**
+ * Return the JDBC properties needed for the connection.
+ */
+ def getJdbcProperties(): Properties = new Properties()
+
/**
* Optional entry point when container starts
*
@@ -118,6 +129,7 @@ abstract class DockerJDBCIntegrationSuite extends SharedSparkSession with Eventu
port
}
val hostConfigBuilder = HostConfig.builder()
+ .privileged(db.privileged)
.networkMode("bridge")
.ipcMode(if (db.usesIpc) "host" else "")
.portBindings(
@@ -142,12 +154,11 @@ abstract class DockerJDBCIntegrationSuite extends SharedSparkSession with Eventu
// Start the container and wait until the database can accept JDBC connections:
docker.startContainer(containerId)
jdbcUrl = db.getJdbcUrl(dockerIp, externalPort)
- eventually(timeout(1.minute), interval(1.second)) {
- val conn = java.sql.DriverManager.getConnection(jdbcUrl)
- conn.close()
+ var conn: Connection = null
+ eventually(timeout(2.minutes), interval(1.second)) {
+ conn = getConnection()
}
// Run any setup queries:
- val conn: Connection = java.sql.DriverManager.getConnection(jdbcUrl)
try {
dataPreparation(conn)
} finally {
@@ -183,6 +194,13 @@ abstract class DockerJDBCIntegrationSuite extends SharedSparkSession with Eventu
}
}
+ /**
+ * Return the JDBC connection.
+ */
+ def getConnection(): Connection = {
+ DriverManager.getConnection(jdbcUrl, db.getJdbcProperties())
+ }
+
/**
* Prepare databases and tables for testing.
*/
diff --git a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DockerKrbJDBCIntegrationSuite.scala b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DockerKrbJDBCIntegrationSuite.scala
index 009b4a2b1b32e..c20c006f3b8b6 100644
--- a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DockerKrbJDBCIntegrationSuite.scala
+++ b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/DockerKrbJDBCIntegrationSuite.scala
@@ -77,6 +77,8 @@ abstract class DockerKrbJDBCIntegrationSuite extends DockerJDBCIntegrationSuite
}
}
+ protected def replaceIp(s: String): String = s.replace("__IP_ADDRESS_REPLACE_ME__", dockerIp)
+
protected def copyExecutableResource(
fileName: String, dir: File, processLine: String => String = identity) = {
val newEntry = new File(dir.getAbsolutePath, fileName)
@@ -100,7 +102,7 @@ abstract class DockerKrbJDBCIntegrationSuite extends DockerJDBCIntegrationSuite
}
override def dataPreparation(conn: Connection): Unit = {
- conn.prepareStatement("CREATE TABLE bar (c0 text)").executeUpdate()
+ conn.prepareStatement("CREATE TABLE bar (c0 VARCHAR(8))").executeUpdate()
conn.prepareStatement("INSERT INTO bar VALUES ('hello')").executeUpdate()
}
diff --git a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/MariaDBKrbIntegrationSuite.scala b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/MariaDBKrbIntegrationSuite.scala
index 7c1adc990bab3..9b9d15517d572 100644
--- a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/MariaDBKrbIntegrationSuite.scala
+++ b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/MariaDBKrbIntegrationSuite.scala
@@ -46,7 +46,6 @@ class MariaDBKrbIntegrationSuite extends DockerKrbJDBCIntegrationSuite {
override def beforeContainerStart(
hostConfigBuilder: HostConfig.Builder,
containerConfigBuilder: ContainerConfig.Builder): Unit = {
- def replaceIp(s: String): String = s.replace("__IP_ADDRESS_REPLACE_ME__", dockerIp)
copyExecutableResource("mariadb_docker_entrypoint.sh", entryPointDir, replaceIp)
copyExecutableResource("mariadb_krb_setup.sh", initDbDir, replaceIp)
diff --git a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/PostgresKrbIntegrationSuite.scala b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/PostgresKrbIntegrationSuite.scala
index adf30fbdc1e12..e94bf3dd588aa 100644
--- a/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/PostgresKrbIntegrationSuite.scala
+++ b/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/PostgresKrbIntegrationSuite.scala
@@ -43,7 +43,6 @@ class PostgresKrbIntegrationSuite extends DockerKrbJDBCIntegrationSuite {
override def beforeContainerStart(
hostConfigBuilder: HostConfig.Builder,
containerConfigBuilder: ContainerConfig.Builder): Unit = {
- def replaceIp(s: String): String = s.replace("__IP_ADDRESS_REPLACE_ME__", dockerIp)
copyExecutableResource("postgres_krb_setup.sh", initDbDir, replaceIp)
hostConfigBuilder.appendBinds(
diff --git a/pom.xml b/pom.xml
index d0a2863bf3e85..34a1a6176deb5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -963,6 +963,12 @@
42.2.6
test
+
+ com.ibm.db2
+ jcc
+ 11.5.0.0
+ test
+
org.apache.curator
curator-recipes
diff --git a/sql/core/pom.xml b/sql/core/pom.xml
index e97c7fd3280be..7c5fcba9c2131 100644
--- a/sql/core/pom.xml
+++ b/sql/core/pom.xml
@@ -140,6 +140,11 @@
postgresql
test
+
+ com.ibm.db2
+ jcc
+ test
+
org.apache.parquet
parquet-avro
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/BasicConnectionProvider.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/BasicConnectionProvider.scala
index a5e3fbd348256..c21e16bcf1280 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/BasicConnectionProvider.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/BasicConnectionProvider.scala
@@ -19,11 +19,17 @@ package org.apache.spark.sql.execution.datasources.jdbc.connection
import java.sql.{Connection, Driver}
+import scala.collection.JavaConverters._
+
import org.apache.spark.sql.execution.datasources.jdbc.JDBCOptions
private[jdbc] class BasicConnectionProvider(driver: Driver, options: JDBCOptions)
extends ConnectionProvider {
def getConnection(): Connection = {
- driver.connect(options.url, options.asConnectionProperties)
+ val properties = getAdditionalProperties()
+ options.asConnectionProperties.entrySet().asScala.foreach { e =>
+ properties.put(e.getKey(), e.getValue())
+ }
+ driver.connect(options.url, properties)
}
}
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProvider.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProvider.scala
index c864f1f52fcce..73e73e59be574 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProvider.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/ConnectionProvider.scala
@@ -18,6 +18,7 @@
package org.apache.spark.sql.execution.datasources.jdbc.connection
import java.sql.{Connection, Driver}
+import java.util.Properties
import org.apache.spark.internal.Logging
import org.apache.spark.sql.execution.datasources.jdbc.JDBCOptions
@@ -28,6 +29,11 @@ import org.apache.spark.sql.execution.datasources.jdbc.JDBCOptions
* the parameters.
*/
private[jdbc] trait ConnectionProvider {
+ /**
+ * Additional properties for data connection (Data source property takes precedence).
+ */
+ def getAdditionalProperties(): Properties = new Properties()
+
/**
* Opens connection toward the database.
*/
@@ -50,6 +56,10 @@ private[jdbc] object ConnectionProvider extends Logging {
logDebug("MariaDB connection provider found")
new MariaDBConnectionProvider(driver, options)
+ case DB2ConnectionProvider.driverClass =>
+ logDebug("DB2 connection provider found")
+ new DB2ConnectionProvider(driver, options)
+
case _ =>
throw new IllegalArgumentException(s"Driver ${options.driverClass} does not support " +
"Kerberos authentication")
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProvider.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProvider.scala
new file mode 100644
index 0000000000000..1e9e713e2c4d4
--- /dev/null
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProvider.scala
@@ -0,0 +1,61 @@
+/*
+ * 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.spark.sql.execution.datasources.jdbc.connection
+
+import java.security.PrivilegedExceptionAction
+import java.sql.{Connection, Driver}
+import java.util.Properties
+
+import org.apache.hadoop.security.UserGroupInformation
+
+import org.apache.spark.sql.execution.datasources.jdbc.JDBCOptions
+
+private[sql] class DB2ConnectionProvider(driver: Driver, options: JDBCOptions)
+ extends SecureConnectionProvider(driver, options) {
+ override val appEntry: String = "JaasClient"
+
+ override def getConnection(): Connection = {
+ setAuthenticationConfigIfNeeded()
+ UserGroupInformation.loginUserFromKeytabAndReturnUGI(options.principal, options.keytab).doAs(
+ new PrivilegedExceptionAction[Connection]() {
+ override def run(): Connection = {
+ DB2ConnectionProvider.super.getConnection()
+ }
+ }
+ )
+ }
+
+ override def getAdditionalProperties(): Properties = {
+ val result = new Properties()
+ // 11 is the integer value for kerberos
+ result.put("securityMechanism", new String("11"))
+ result.put("KerberosServerPrincipal", options.principal)
+ result
+ }
+
+ override def setAuthenticationConfigIfNeeded(): Unit = {
+ val (parent, configEntry) = getConfigWithAppEntry()
+ if (configEntry == null || configEntry.isEmpty) {
+ setAuthenticationConfig(parent)
+ }
+ }
+}
+
+private[sql] object DB2ConnectionProvider {
+ val driverClass = "com.ibm.db2.jcc.DB2Driver"
+}
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/MariaDBConnectionProvider.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/MariaDBConnectionProvider.scala
index eb2f0f78022ba..2b2496f27aa8c 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/MariaDBConnectionProvider.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/MariaDBConnectionProvider.scala
@@ -18,9 +18,6 @@
package org.apache.spark.sql.execution.datasources.jdbc.connection
import java.sql.Driver
-import javax.security.auth.login.Configuration
-
-import scala.collection.JavaConverters._
import org.apache.spark.sql.execution.datasources.jdbc.JDBCOptions
@@ -31,8 +28,7 @@ private[jdbc] class MariaDBConnectionProvider(driver: Driver, options: JDBCOptio
}
override def setAuthenticationConfigIfNeeded(): Unit = {
- val parent = Configuration.getConfiguration
- val configEntry = parent.getAppConfigurationEntry(appEntry)
+ val (parent, configEntry) = getConfigWithAppEntry()
/**
* Couple of things to mention here:
* 1. MariaDB doesn't support JAAS application name configuration
@@ -41,10 +37,7 @@ private[jdbc] class MariaDBConnectionProvider(driver: Driver, options: JDBCOptio
val entryUsesKeytab = configEntry != null &&
configEntry.exists(_.getOptions().get("useKeyTab") == "true")
if (configEntry == null || configEntry.isEmpty || !entryUsesKeytab) {
- val config = new SecureConnectionProvider.JDBCConfiguration(
- parent, appEntry, options.keytab, options.principal)
- logDebug("Adding database specific security configuration")
- Configuration.setConfiguration(config)
+ setAuthenticationConfig(parent)
}
}
}
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/PostgresConnectionProvider.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/PostgresConnectionProvider.scala
index 14911fc75ebc1..f36f7d76be087 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/PostgresConnectionProvider.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/PostgresConnectionProvider.scala
@@ -19,7 +19,6 @@ package org.apache.spark.sql.execution.datasources.jdbc.connection
import java.sql.Driver
import java.util.Properties
-import javax.security.auth.login.Configuration
import org.apache.spark.sql.execution.datasources.jdbc.JDBCOptions
@@ -32,13 +31,9 @@ private[jdbc] class PostgresConnectionProvider(driver: Driver, options: JDBCOpti
}
override def setAuthenticationConfigIfNeeded(): Unit = {
- val parent = Configuration.getConfiguration
- val configEntry = parent.getAppConfigurationEntry(appEntry)
+ val (parent, configEntry) = getConfigWithAppEntry()
if (configEntry == null || configEntry.isEmpty) {
- val config = new SecureConnectionProvider.JDBCConfiguration(
- parent, appEntry, options.keytab, options.principal)
- logDebug("Adding database specific security configuration")
- Configuration.setConfiguration(config)
+ setAuthenticationConfig(parent)
}
}
}
diff --git a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/SecureConnectionProvider.scala b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/SecureConnectionProvider.scala
index ff192d71e6f33..1b54e9509b9eb 100644
--- a/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/SecureConnectionProvider.scala
+++ b/sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/SecureConnectionProvider.scala
@@ -43,6 +43,18 @@ private[jdbc] abstract class SecureConnectionProvider(driver: Driver, options: J
* then later calls must be no op.
*/
def setAuthenticationConfigIfNeeded(): Unit
+
+ protected def getConfigWithAppEntry(): (Configuration, Array[AppConfigurationEntry]) = {
+ val parent = Configuration.getConfiguration
+ (parent, parent.getAppConfigurationEntry(appEntry))
+ }
+
+ protected def setAuthenticationConfig(parent: Configuration) = {
+ val config = new SecureConnectionProvider.JDBCConfiguration(
+ parent, appEntry, options.keytab, options.principal)
+ logDebug("Adding database specific security configuration")
+ Configuration.setConfiguration(config)
+ }
}
object SecureConnectionProvider {
diff --git a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProviderSuite.scala b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProviderSuite.scala
new file mode 100644
index 0000000000000..d656f83e2ebb9
--- /dev/null
+++ b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/jdbc/connection/DB2ConnectionProviderSuite.scala
@@ -0,0 +1,27 @@
+/*
+ * 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.spark.sql.execution.datasources.jdbc.connection
+
+class DB2ConnectionProviderSuite extends ConnectionProviderSuiteBase {
+ test("setAuthenticationConfigIfNeeded must set authentication if not set") {
+ val driver = registerDriver(DB2ConnectionProvider.driverClass)
+ val provider = new DB2ConnectionProvider(driver, options("jdbc:db2://localhost/db2"))
+
+ testSecureConnectionProvider(provider)
+ }
+}