Skip to content

Commit 54aabb0

Browse files
dtenedorHyukjinKwon
authored andcommitted
[SPARK-39350][SQL] Add flag to control breaking change process for: DESC NAMESPACE EXTENDED should redact properties
### What changes were proposed in this pull request? Add a flag to control breaking change process for: DESC NAMESPACE EXTENDED should redact properties. ### Why are the changes needed? This lets Spark users control how the new behavior rolls out to users. ### Does this PR introduce _any_ user-facing change? No. ### How was this patch tested? This PR extends unit test coverage. Closes apache#36799 from dtenedor/desc-namespace-breaking-change. Authored-by: Daniel Tenedorio <[email protected]> Signed-off-by: Hyukjin Kwon <[email protected]>
1 parent 6a74378 commit 54aabb0

File tree

4 files changed

+58
-21
lines changed

4 files changed

+58
-21
lines changed

sql/catalyst/src/main/scala/org/apache/spark/sql/internal/SQLConf.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3818,6 +3818,16 @@ object SQLConf {
38183818
.booleanConf
38193819
.createWithDefault(false)
38203820

3821+
val LEGACY_DESC_NAMESPACE_REDACT_PROPERTIES =
3822+
buildConf("spark.sql.legacy.descNamespaceRedactProperties")
3823+
.internal()
3824+
.doc("When set to false, redact sensitive information in the result of DESC NAMESPACE " +
3825+
"EXTENDED. If set to true, it restores the legacy behavior that this sensitive " +
3826+
"information was included in the output.")
3827+
.version("3.4.0")
3828+
.booleanConf
3829+
.createWithDefault(false)
3830+
38213831
/**
38223832
* Holds information about keys that have been deprecated.
38233833
*

sql/core/src/main/scala/org/apache/spark/sql/execution/command/ddl.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ case class DescribeDatabaseCommand(
190190
val propertiesStr =
191191
if (properties.isEmpty) {
192192
""
193+
} else if (SQLConf.get.getConf(SQLConf.LEGACY_DESC_NAMESPACE_REDACT_PROPERTIES)) {
194+
properties.toSeq.sortBy(_._1).mkString("(", ", ", ")")
193195
} else {
194196
conf.redactOptions(properties).toSeq.sortBy(_._1).mkString("(", ", ", ")")
195197
}

sql/core/src/main/scala/org/apache/spark/sql/execution/datasources/v2/DescribeNamespaceExec.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import scala.collection.mutable.ArrayBuffer
2323
import org.apache.spark.sql.catalyst.InternalRow
2424
import org.apache.spark.sql.catalyst.expressions.Attribute
2525
import org.apache.spark.sql.connector.catalog.{CatalogV2Util, SupportsNamespaces}
26+
import org.apache.spark.sql.internal.SQLConf
2627

2728
/**
2829
* Physical plan node for describing a namespace.
@@ -48,6 +49,8 @@ case class DescribeNamespaceExec(
4849
val propertiesStr =
4950
if (properties.isEmpty) {
5051
""
52+
} else if (SQLConf.get.getConf(SQLConf.LEGACY_DESC_NAMESPACE_REDACT_PROPERTIES)) {
53+
properties.toSeq.sortBy(_._1).mkString("(", ", ", ")")
5154
} else {
5255
conf.redactOptions(properties.toMap).toSeq.sortBy(_._1).mkString("(", ", ", ")")
5356
}

sql/core/src/test/scala/org/apache/spark/sql/execution/command/v2/DescribeNamespaceSuite.scala

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package org.apache.spark.sql.execution.command.v2
2020
import org.apache.spark.sql.Row
2121
import org.apache.spark.sql.connector.catalog.SupportsNamespaces
2222
import org.apache.spark.sql.execution.command
23+
import org.apache.spark.sql.internal.SQLConf
2324
import org.apache.spark.sql.types.{BooleanType, MetadataBuilder, StringType, StructType}
2425
import org.apache.spark.util.Utils
2526

@@ -30,28 +31,49 @@ class DescribeNamespaceSuite extends command.DescribeNamespaceSuiteBase with Com
3031
override def notFoundMsgPrefix: String = "Namespace"
3132

3233
test("DescribeNamespace using v2 catalog") {
33-
withNamespace(s"$catalog.ns1.ns2") {
34-
sql(
35-
s"""
36-
| CREATE NAMESPACE IF NOT EXISTS $catalog.ns1.ns2
37-
| COMMENT 'test namespace'
38-
| LOCATION '/tmp/ns_test'
39-
| WITH DBPROPERTIES (password = 'password')
34+
withSQLConf(SQLConf.LEGACY_DESC_NAMESPACE_REDACT_PROPERTIES.key -> "false") {
35+
withNamespace(s"$catalog.ns1.ns2") {
36+
sql(
37+
s"""
38+
| CREATE NAMESPACE IF NOT EXISTS $catalog.ns1.ns2
39+
| COMMENT 'test namespace'
40+
| LOCATION '/tmp/ns_test'
41+
| WITH DBPROPERTIES (password = 'password')
4042
""".stripMargin)
41-
val descriptionDf = sql(s"DESCRIBE NAMESPACE EXTENDED $catalog.ns1.ns2")
42-
assert(descriptionDf.schema.map(field => (field.name, field.dataType)) ===
43-
Seq(
44-
("info_name", StringType),
45-
("info_value", StringType)
46-
))
47-
val description = descriptionDf.collect()
48-
assert(description === Seq(
49-
Row("Namespace Name", "ns2"),
50-
Row(SupportsNamespaces.PROP_COMMENT.capitalize, "test namespace"),
51-
Row(SupportsNamespaces.PROP_LOCATION.capitalize, "file:/tmp/ns_test"),
52-
Row(SupportsNamespaces.PROP_OWNER.capitalize, Utils.getCurrentUserName()),
53-
Row("Properties", "((password,*********(redacted)))"))
54-
)
43+
val descriptionDf = sql(s"DESCRIBE NAMESPACE EXTENDED $catalog.ns1.ns2")
44+
assert(descriptionDf.schema.map(field => (field.name, field.dataType)) ===
45+
Seq(
46+
("info_name", StringType),
47+
("info_value", StringType)
48+
))
49+
val description = descriptionDf.collect()
50+
assert(description === Seq(
51+
Row("Namespace Name", "ns2"),
52+
Row(SupportsNamespaces.PROP_COMMENT.capitalize, "test namespace"),
53+
Row(SupportsNamespaces.PROP_LOCATION.capitalize, "file:/tmp/ns_test"),
54+
Row(SupportsNamespaces.PROP_OWNER.capitalize, Utils.getCurrentUserName()),
55+
Row("Properties", "((password,*********(redacted)))"))
56+
)
57+
}
58+
}
59+
withSQLConf(SQLConf.LEGACY_DESC_NAMESPACE_REDACT_PROPERTIES.key -> "true") {
60+
withNamespace(s"$catalog.ns1.ns2") {
61+
sql(s"CREATE NAMESPACE IF NOT EXISTS $catalog.ns1.ns2 COMMENT " +
62+
"'test namespace' LOCATION '/tmp/ns_test'")
63+
val descriptionDf = sql(s"DESCRIBE NAMESPACE $catalog.ns1.ns2")
64+
assert(descriptionDf.schema.map(field => (field.name, field.dataType)) ===
65+
Seq(
66+
("info_name", StringType),
67+
("info_value", StringType)
68+
))
69+
val description = descriptionDf.collect()
70+
assert(description === Seq(
71+
Row("Namespace Name", "ns2"),
72+
Row(SupportsNamespaces.PROP_COMMENT.capitalize, "test namespace"),
73+
Row(SupportsNamespaces.PROP_LOCATION.capitalize, "file:/tmp/ns_test"),
74+
Row(SupportsNamespaces.PROP_OWNER.capitalize, Utils.getCurrentUserName()))
75+
)
76+
}
5577
}
5678
}
5779

0 commit comments

Comments
 (0)