Skip to content

Commit 3ace9fb

Browse files
opensearch-trigger-bot[bot]github-actions[bot]noCharger
authored
[Backport 0.4] handle MetaException with glue AccessDeniedException (#412)
* handle MetaException with glue AccessDeniedException (#410) * handleGeneralException should handle MetaException with AccessDeniedException properly Signed-off-by: Louis Chu <clingzhi@amazon.com> * Revise comments Signed-off-by: Louis Chu <clingzhi@amazon.com> --------- Signed-off-by: Louis Chu <clingzhi@amazon.com> (cherry picked from commit b5715f6) Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Resolve cherry-pick confict Signed-off-by: Louis Chu <clingzhi@amazon.com> --------- Signed-off-by: Louis Chu <clingzhi@amazon.com> Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Louis Chu <clingzhi@amazon.com>
1 parent bd2e18c commit 3ace9fb

File tree

3 files changed

+52
-9
lines changed

3 files changed

+52
-9
lines changed
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.flint.core.logging
7+
8+
// Define constants for common error messages
9+
object ExceptionMessages {
10+
val SyntaxErrorPrefix = "Syntax error"
11+
val S3ErrorPrefix = "Fail to read data from S3. Cause"
12+
val GlueErrorPrefix = "Fail to read data from Glue. Cause"
13+
val QueryAnalysisErrorPrefix = "Fail to analyze query. Cause"
14+
val SparkExceptionErrorPrefix = "Spark exception. Cause"
15+
val QueryRunErrorPrefix = "Fail to run query. Cause"
16+
val GlueAccessDeniedMessage = "Access denied in AWS Glue service. Please check permissions."
17+
}

spark-sql-application/src/main/scala/org/apache/spark/sql/FlintJobExecutor.scala

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
1313
import com.fasterxml.jackson.module.scala.DefaultScalaModule
1414
import org.apache.commons.text.StringEscapeUtils.unescapeJava
1515
import org.opensearch.flint.core.IRestHighLevelClient
16-
import org.opensearch.flint.core.logging.{CustomLogging, OperationMessage}
16+
import org.opensearch.flint.core.logging.{CustomLogging, ExceptionMessages, OperationMessage}
1717
import org.opensearch.flint.core.metrics.MetricConstants
1818
import org.opensearch.flint.core.metrics.MetricsUtil.incrementCounter
1919
import play.api.libs.json._
@@ -454,34 +454,43 @@ trait FlintJobExecutor {
454454
def processQueryException(ex: Exception): String = {
455455
getRootCause(ex) match {
456456
case r: ParseException =>
457-
handleQueryException(r, "Syntax error")
457+
handleQueryException(r, ExceptionMessages.SyntaxErrorPrefix)
458458
case r: AmazonS3Exception =>
459459
incrementCounter(MetricConstants.S3_ERR_CNT_METRIC)
460460
handleQueryException(
461461
r,
462-
"Fail to read data from S3. Cause",
462+
ExceptionMessages.S3ErrorPrefix,
463463
Some(r.getServiceName),
464464
Some(r.getStatusCode))
465465
case r: AWSGlueException =>
466466
incrementCounter(MetricConstants.GLUE_ERR_CNT_METRIC)
467467
// Redact Access denied in AWS Glue service
468468
r match {
469469
case accessDenied: AccessDeniedException =>
470-
accessDenied.setErrorMessage(
471-
"Access denied in AWS Glue service. Please check permissions.")
470+
accessDenied.setErrorMessage(ExceptionMessages.GlueAccessDeniedMessage)
472471
case _ => // No additional action for other types of AWSGlueException
473472
}
474473
handleQueryException(
475474
r,
476-
"Fail to read data from Glue. Cause",
475+
ExceptionMessages.GlueErrorPrefix,
477476
Some(r.getServiceName),
478477
Some(r.getStatusCode))
479478
case r: AnalysisException =>
480-
handleQueryException(r, "Fail to analyze query. Cause")
479+
handleQueryException(r, ExceptionMessages.QueryAnalysisErrorPrefix)
481480
case r: SparkException =>
482-
handleQueryException(r, "Spark exception. Cause")
481+
handleQueryException(r, ExceptionMessages.SparkExceptionErrorPrefix)
483482
case r: Exception =>
484-
handleQueryException(r, "Fail to run query. Cause")
483+
val rootCauseClassName = ex.getClass.getName
484+
val errMsg = ex.getMessage
485+
logDebug(s"Root cause class name: $rootCauseClassName")
486+
logDebug(s"Root cause error message: $errMsg")
487+
if (rootCauseClassName == "org.apache.hadoop.hive.metastore.api.MetaException" &&
488+
errMsg.contains("com.amazonaws.services.glue.model.AccessDeniedException")) {
489+
val e = new SecurityException(ExceptionMessages.GlueAccessDeniedMessage)
490+
handleQueryException(e, ExceptionMessages.QueryRunErrorPrefix)
491+
} else {
492+
handleQueryException(ex, ExceptionMessages.QueryRunErrorPrefix)
493+
}
485494
}
486495
}
487496

spark-sql-application/src/test/scala/org/apache/spark/sql/FlintREPLTest.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,23 @@ class FlintREPLTest
464464
assert(result == expectedError)
465465
}
466466

467+
test("handleGeneralException should handle MetaException with AccessDeniedException properly") {
468+
val mockFlintCommand = mock[FlintCommand]
469+
470+
// Simulate the root cause being MetaException
471+
val exception = new org.apache.hadoop.hive.metastore.api.MetaException(
472+
"AWSCatalogMetastoreClient: Unable to verify existence of default database: com.amazonaws.services.glue.model.AccessDeniedException: User: ****** is not authorized to perform: ******")
473+
474+
val result = FlintREPL.processQueryException(exception, mockFlintCommand)
475+
476+
val expectedError =
477+
"""{"Message":"Fail to run query. Cause: Access denied in AWS Glue service. Please check permissions."}"""
478+
479+
result shouldEqual expectedError
480+
verify(mockFlintCommand).fail()
481+
verify(mockFlintCommand).error = Some(expectedError)
482+
}
483+
467484
test("Doc Exists and excludeJobIds is an ArrayList Containing JobId") {
468485
val sessionId = "session123"
469486
val jobId = "jobABC"

0 commit comments

Comments
 (0)