This is an automated email from the ASF dual-hosted git repository. bowenliang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/kyuubi.git
The following commit(s) were added to refs/heads/master by this push: new fd69c6ee1 [KYUUBI #5407][AUTHZ] Tests for Iceberg system procedures of snapshot management fd69c6ee1 is described below commit fd69c6ee1dd40b7c4f496c74a45f574220448bc6 Author: chenliang.lu <marssss2...@gmail.com> AuthorDate: Thu Oct 12 09:58:16 2023 +0800 [KYUUBI #5407][AUTHZ] Tests for Iceberg system procedures of snapshot management ### _Why are the changes needed?_ To close #5407 . Follow up for https://github.com/apache/kyuubi/pull/5248 . Add some UT for snapshot management procedures. These procedures require alter permissions. 1. rollback_to_snapshot (https://iceberg.apache.org/docs/latest/spark-procedures/#rollback_to_snapshot): Usage: `CALL catalog_name.system.rollback_to_snapshot('db.sample', 1) ` Meaning: rollback a table to a specific snapshot ID. 2. rollback_to_timestamp (https://iceberg.apache.org/docs/latest/spark-procedures/#rollback_to_timestamp) Usage: `CALL catalog_name.system.rollback_to_timestamp('db.sample', TIMESTAMP '2021-06-30 00:00:00')` Meaning: rollback the table to the latest snapshot less than time. 3. set_current_snapshot (https://iceberg.apache.org/docs/latest/spark-procedures/#set_current_snapshot) Usage: `CALL catalog_name.system.set_current_snapshot('db.sample', 1)` Meaning: Set a table to a specific snapshot ID. ### _How was this patch tested?_ - [x] Add some test cases that check the changes thoroughly including negative and positive cases if possible - [ ] Add screenshots for manual tests if appropriate - [x] [Run test](https://kyuubi.readthedocs.io/en/master/contributing/code/testing.html#running-tests) locally before make a pull request ### _Was this patch authored or co-authored using generative AI tooling?_ No Closes #5394 from yabola/add_call. Closes #5407 98b7492e0 [Bowen Liang] split into 3 ut for snapshot management 23fe49ae4 [Bowen Liang] refactor ut 8ba97c6ef [chenliang.lu] Add UT for checking previleges in iceberg call snapshot management Lead-authored-by: chenliang.lu <marssss2...@gmail.com> Co-authored-by: Bowen Liang <liangbo...@gf.com.cn> Signed-off-by: Bowen Liang <liangbo...@gf.com.cn> --- .../IcebergCatalogRangerSparkExtensionSuite.scala | 66 +++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/IcebergCatalogRangerSparkExtensionSuite.scala b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/IcebergCatalogRangerSparkExtensionSuite.scala index e33fbb7a3..492880553 100644 --- a/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/IcebergCatalogRangerSparkExtensionSuite.scala +++ b/extensions/spark/kyuubi-spark-authz/src/test/scala/org/apache/kyuubi/plugin/spark/authz/ranger/IcebergCatalogRangerSparkExtensionSuite.scala @@ -16,11 +16,15 @@ */ package org.apache.kyuubi.plugin.spark.authz.ranger -// scalastyle:off +import java.sql.Timestamp +import java.text.SimpleDateFormat + import scala.util.Try +import org.apache.spark.sql.Row import org.scalatest.Outcome +// scalastyle:off import org.apache.kyuubi.Utils import org.apache.kyuubi.plugin.spark.authz.AccessControlException import org.apache.kyuubi.plugin.spark.authz.RangerTestNamespace._ @@ -281,4 +285,64 @@ class IcebergCatalogRangerSparkExtensionSuite extends RangerSparkExtensionSuite }) } } + + private def prepareExampleIcebergTable(table: String, initSnapshots: Int): Unit = { + doAs(admin, sql(s"CREATE TABLE IF NOT EXISTS $table (id int, name string) USING iceberg")) + (0 until initSnapshots).foreach(i => + doAs(admin, sql(s"INSERT INTO $table VALUES ($i, 'user_$i')"))) + } + + private def getFirstSnapshot(table: String): Row = { + val existedSnapshots = + sql(s"SELECT * FROM $table.snapshots ORDER BY committed_at ASC LIMIT 1").collect() + existedSnapshots(0) + } + + test("CALL rollback_to_snapshot") { + val tableName = "table_rollback_to_snapshot" + val table = s"$catalogV2.$namespace1.$tableName" + withCleanTmpResources(Seq((table, "table"))) { + prepareExampleIcebergTable(table, 2) + val targetSnapshotId = getFirstSnapshot(table).getAs[Long]("snapshot_id") + val callRollbackToSnapshot = + s"CALL $catalogV2.system.rollback_to_snapshot (table => '$table', snapshot_id => $targetSnapshotId)" + + interceptContains[AccessControlException](doAs(someone, sql(callRollbackToSnapshot)))( + s"does not have [alter] privilege on [$namespace1/$tableName]") + doAs(admin, sql(callRollbackToSnapshot)) + } + } + + test("CALL rollback_to_timestamp") { + val tableName = "table_rollback_to_timestamp" + val table = s"$catalogV2.$namespace1.$tableName" + withCleanTmpResources(Seq((table, "table"))) { + prepareExampleIcebergTable(table, 2) + val callRollbackToTimestamp = { + val targetSnapshotCommittedAt = getFirstSnapshot(table).getAs[Timestamp]("committed_at") + val targetTimestamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") + .format(targetSnapshotCommittedAt.getTime + 1) + s"CALL $catalogV2.system.rollback_to_timestamp (table => '$table', timestamp => TIMESTAMP '$targetTimestamp')" + } + + interceptContains[AccessControlException](doAs(someone, sql(callRollbackToTimestamp)))( + s"does not have [alter] privilege on [$namespace1/$tableName]") + doAs(admin, sql(callRollbackToTimestamp)) + } + } + + test("CALL set_current_snapshot") { + val tableName = "table_set_current_snapshot" + val table = s"$catalogV2.$namespace1.$tableName" + withCleanTmpResources(Seq((table, "table"))) { + prepareExampleIcebergTable(table, 2) + val targetSnapshotId = getFirstSnapshot(table).getAs[Long]("snapshot_id") + val callSetCurrentSnapshot = + s"CALL $catalogV2.system.set_current_snapshot (table => '$table', snapshot_id => $targetSnapshotId)" + + interceptContains[AccessControlException](doAs(someone, sql(callSetCurrentSnapshot)))( + s"does not have [alter] privilege on [$namespace1/$tableName]") + doAs(admin, sql(callSetCurrentSnapshot)) + } + } }