Skip to content

Commit 9ec426d

Browse files
yaooqinnMaxGekk
authored andcommitted
[SPARK-46592][DOCKER][TEST] OracleIntegrationSuite is flaky because of ORA-04021
### What changes were proposed in this pull request? This PR mounts `docker-entrypoint-initdb.d` to OracleDocker to set DDL_LOCK_TIMEOUT and retry `alter user system` to ensure the password of SYSTEM user is correctly set. ### Why are the changes needed? https://github.com/apache/spark/actions/runs/7405337059/job/20148144542 https://github.com/apache/spark/actions/runs/7403889993/job/20144539155 https://github.com/apache/spark/actions/runs/7401841987/job/20138483574 Fix test flakiness caused by ORA-04021 ``` 22:09.284 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: CONTAINER: Resetting SYS and SYSTEM passwords. 24/01/04 04:22:09.284 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: 24/01/04 04:22:09.284 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: User altered. 24/01/04 04:22:09.284 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: 24/01/04 04:22:09.284 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: ALTER USER SYSTEM IDENTIFIED BY "Th1s1sThe0racle#Pass" 24/01/04 04:22:09.284 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: * 24/01/04 04:22:09.284 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: ERROR at line 1: 24/01/04 04:22:09.285 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: ORA-65048: error encountered when processing the current DDL statement in 24/01/04 04:22:09.285 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: pluggable database FREEPDB1 24/01/04 04:22:09.285 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: ORA-04021: timeout occurred while waiting to lock object 24/01/04 04:22:09.285 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: Help: https://docs.oracle.com/error-help/db/ora-65048/ 24/01/04 04:22:09.285 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: 24/01/04 04:22:09.285 docker-java-stream-568158377 INFO OracleIntegrationSuite: STDOUT: ``` ### Does this PR introduce _any_ user-facing change? no ### How was this patch tested? OracleIntegrationSuite ### Was this patch authored or co-authored using generative AI tooling? no Closes #44594 from yaooqinn/SPARK-46592. Authored-by: Kent Yao <yao@apache.org> Signed-off-by: Max Gekk <max.gekk@gmail.com>
1 parent ae2e00e commit 9ec426d

4 files changed

Lines changed: 72 additions & 41 deletions

File tree

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.spark.sql.jdbc
19+
20+
import java.io.{File, PrintWriter}
21+
22+
import com.github.dockerjava.api.model._
23+
24+
import org.apache.spark.internal.Logging
25+
import org.apache.spark.util.Utils
26+
27+
class OracleDatabaseOnDocker extends DatabaseOnDocker with Logging {
28+
lazy override val imageName =
29+
sys.env.getOrElse("ORACLE_DOCKER_IMAGE_NAME", "gvenzl/oracle-free:23.3")
30+
val oracle_password = "Th1s1sThe0racle#Pass"
31+
override val env = Map(
32+
"ORACLE_PWD" -> oracle_password, // oracle images uses this
33+
"ORACLE_PASSWORD" -> oracle_password // gvenzl/oracle-free uses this
34+
)
35+
override val usesIpc = false
36+
override val jdbcPort: Int = 1521
37+
38+
override def getJdbcUrl(ip: String, port: Int): String = {
39+
s"jdbc:oracle:thin:system/$oracle_password@//$ip:$port/freepdb1"
40+
}
41+
42+
override def beforeContainerStart(
43+
hostConfigBuilder: HostConfig,
44+
containerConfigBuilder: ContainerConfig): Unit = {
45+
try {
46+
val dir = Utils.createTempDir()
47+
val writer = new PrintWriter(new File(dir, "install.sql"))
48+
// SPARK-46592: gvenzl/oracle-free occasionally fails to start with the following error:
49+
// 'ORA-04021: timeout occurred while waiting to lock object', when initializing the
50+
// SYSTEM user. This is due to the fact that the default DDL_LOCK_TIMEOUT is 0, which
51+
// means that the lock will no wait. We set the timeout to 30 seconds to try again.
52+
// TODO: This workaround should be removed once the issue is fixed in the image.
53+
// https://github.com/gvenzl/oci-oracle-free/issues/35
54+
writer.write("ALTER SESSION SET DDL_LOCK_TIMEOUT = 30;")
55+
writer.write(s"""ALTER USER SYSTEM IDENTIFIED BY "$oracle_password";""")
56+
writer.close()
57+
val newBind = new Bind(
58+
dir.getAbsolutePath,
59+
new Volume("/docker-entrypoint-initdb.d"),
60+
AccessMode.ro)
61+
hostConfigBuilder.withBinds(hostConfigBuilder.getBinds :+ newBind: _*)
62+
} catch {
63+
case e: Exception =>
64+
logWarning("Failed to create install.sql file", e)
65+
}
66+
}
67+
}

connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/OracleIntegrationSuite.scala

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,7 @@ import org.apache.spark.tags.DockerTest
6565
class OracleIntegrationSuite extends DockerJDBCIntegrationSuite with SharedSparkSession {
6666
import testImplicits._
6767

68-
override val db = new DatabaseOnDocker {
69-
lazy override val imageName =
70-
sys.env.getOrElse("ORACLE_DOCKER_IMAGE_NAME", "gvenzl/oracle-free:23.3")
71-
val oracle_password = "Th1s1sThe0racle#Pass"
72-
override val env = Map(
73-
"ORACLE_PWD" -> oracle_password, // oracle images uses this
74-
"ORACLE_PASSWORD" -> oracle_password // gvenzl/oracle-free uses this
75-
)
76-
override val usesIpc = false
77-
override val jdbcPort: Int = 1521
78-
override def getJdbcUrl(ip: String, port: Int): String =
79-
s"jdbc:oracle:thin:system/$oracle_password@//$ip:$port/freepdb1"
80-
}
68+
override val db = new OracleDatabaseOnDocker
8169

8270
override val connectionTimeout = timeout(7.minutes)
8371

connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/OracleIntegrationSuite.scala

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import org.apache.spark.{SparkConf, SparkRuntimeException}
2626
import org.apache.spark.sql.AnalysisException
2727
import org.apache.spark.sql.catalyst.util.CharVarcharUtils.CHAR_VARCHAR_TYPE_STRING_METADATA_KEY
2828
import org.apache.spark.sql.execution.datasources.v2.jdbc.JDBCTableCatalog
29-
import org.apache.spark.sql.jdbc.DatabaseOnDocker
29+
import org.apache.spark.sql.jdbc.OracleDatabaseOnDocker
3030
import org.apache.spark.sql.types._
3131
import org.apache.spark.tags.DockerTest
3232

@@ -75,19 +75,7 @@ class OracleIntegrationSuite extends DockerJDBCIntegrationV2Suite with V2JDBCTes
7575

7676
override val catalogName: String = "oracle"
7777
override val namespaceOpt: Option[String] = Some("SYSTEM")
78-
override val db = new DatabaseOnDocker {
79-
lazy override val imageName =
80-
sys.env.getOrElse("ORACLE_DOCKER_IMAGE_NAME", "gvenzl/oracle-free:23.3")
81-
val oracle_password = "Th1s1sThe0racle#Pass"
82-
override val env = Map(
83-
"ORACLE_PWD" -> oracle_password, // oracle images uses this
84-
"ORACLE_PASSWORD" -> oracle_password // gvenzl/oracle-free uses this
85-
)
86-
override val usesIpc = false
87-
override val jdbcPort: Int = 1521
88-
override def getJdbcUrl(ip: String, port: Int): String =
89-
s"jdbc:oracle:thin:system/$oracle_password@//$ip:$port/freepdb1"
90-
}
78+
override val db = new OracleDatabaseOnDocker
9179

9280
override val defaultMetadata: Metadata = new MetadataBuilder()
9381
.putLong("scale", 0)

connector/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/v2/OracleNamespaceSuite.scala

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import java.sql.Connection
2121

2222
import scala.jdk.CollectionConverters._
2323

24-
import org.apache.spark.sql.jdbc.{DatabaseOnDocker, DockerJDBCIntegrationSuite}
24+
import org.apache.spark.sql.jdbc.{DockerJDBCIntegrationSuite, OracleDatabaseOnDocker}
2525
import org.apache.spark.sql.util.CaseInsensitiveStringMap
2626
import org.apache.spark.tags.DockerTest
2727

@@ -57,19 +57,7 @@ class OracleNamespaceSuite extends DockerJDBCIntegrationSuite with V2JDBCNamespa
5757

5858
override def excluded: Seq[String] = Seq("listNamespaces: basic behavior", "Drop namespace")
5959

60-
override val db = new DatabaseOnDocker {
61-
lazy override val imageName =
62-
sys.env.getOrElse("ORACLE_DOCKER_IMAGE_NAME", "gvenzl/oracle-free:23.3")
63-
val oracle_password = "Th1s1sThe0racle#Pass"
64-
override val env = Map(
65-
"ORACLE_PWD" -> oracle_password, // oracle images uses this
66-
"ORACLE_PASSWORD" -> oracle_password // gvenzl/oracle-free uses this
67-
)
68-
override val usesIpc = false
69-
override val jdbcPort: Int = 1521
70-
override def getJdbcUrl(ip: String, port: Int): String =
71-
s"jdbc:oracle:thin:system/$oracle_password@//$ip:$port/freepdb1"
72-
}
60+
override val db = new OracleDatabaseOnDocker
7361

7462
val map = new CaseInsensitiveStringMap(
7563
Map("url" -> db.getJdbcUrl(dockerIp, externalPort),

0 commit comments

Comments
 (0)