Skip to content

Commit 21649e3

Browse files
ajithmedongjoon-hyun
authored andcommitted
[SPARK-27122][CORE][2.4] Jetty classes must not be return via getters in org.apache.spark.ui.WebUI
### What changes were proposed in this pull request? This is a backport of #24088 to avoid CCE. ### Why are the changes needed? When we run YarnSchedulerBackendSuite, the class path seems to be made from the classes folder(`resource-managers/yarn/target/scala-2.12/classes`) instead of jar (`resource-managers/yarn/target/spark-yarn_2.12-*-SNAPSHOT.jar`) . `ui.getHandlers` is in spark-core and its loaded from spark-core.jar which is shaded and hence refers to `org.spark_project.jetty.servlet.ServletContextHandler` Here in org.apache.spark.scheduler.cluster.YarnSchedulerBackend, as its not shaded, it expects org.eclipse.jetty.servlet.ServletContextHandler Refer discussion https://issues.apache.org/jira/browse/SPARK-27122?focusedCommentId=16792318&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#comment-16792318 Hence as a fix, org.apache.spark.ui.WebUI must only return a wrapper class instance or references so that Jetty classes can be avoided in getters which are accessed outside spark-core ### Does this PR introduce any user-facing change? No. ### How was this patch tested? Pass the Jenkins with the existing tests. Closes #25793 from dongjoon-hyun/SPARK-27122. Authored-by: Ajith <ajith2489@gmail.com> Signed-off-by: Dongjoon Hyun <dhyun@apple.com>
1 parent 58ad3e6 commit 21649e3

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

core/src/main/scala/org/apache/spark/ui/WebUI.scala

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717

1818
package org.apache.spark.ui
1919

20-
import javax.servlet.http.HttpServletRequest
20+
import java.util.EnumSet
21+
import javax.servlet.DispatcherType
22+
import javax.servlet.http.{HttpServlet, HttpServletRequest}
2123

2224
import scala.collection.mutable.ArrayBuffer
2325
import scala.collection.mutable.HashMap
2426
import scala.xml.Node
2527

26-
import org.eclipse.jetty.servlet.ServletContextHandler
28+
import org.eclipse.jetty.servlet.{FilterHolder, FilterMapping, ServletContextHandler, ServletHolder}
2729
import org.json4s.JsonAST.{JNothing, JValue}
2830

2931
import org.apache.spark.{SecurityManager, SparkConf, SSLOptions}
@@ -60,6 +62,10 @@ private[spark] abstract class WebUI(
6062
def getHandlers: Seq[ServletContextHandler] = handlers
6163
def getSecurityManager: SecurityManager = securityManager
6264

65+
def getDelegatingHandlers: Seq[DelegatingServletContextHandler] = {
66+
handlers.map(new DelegatingServletContextHandler(_))
67+
}
68+
6369
/** Attaches a tab to this UI, along with all of its attached pages. */
6470
def attachTab(tab: WebUITab): Unit = {
6571
tab.pages.foreach(attachPage)
@@ -97,6 +103,14 @@ private[spark] abstract class WebUI(
97103
serverInfo.foreach(_.addHandler(handler))
98104
}
99105

106+
/** Attaches a handler to this UI. */
107+
def attachHandler(contextPath: String, httpServlet: HttpServlet, pathSpec: String): Unit = {
108+
val ctx = new ServletContextHandler()
109+
ctx.setContextPath(contextPath)
110+
ctx.addServlet(new ServletHolder(httpServlet), pathSpec)
111+
attachHandler(ctx)
112+
}
113+
100114
/** Detaches a handler from this UI. */
101115
def detachHandler(handler: ServletContextHandler): Unit = {
102116
handlers -= handler
@@ -187,3 +201,32 @@ private[spark] abstract class WebUIPage(var prefix: String) {
187201
def render(request: HttpServletRequest): Seq[Node]
188202
def renderJson(request: HttpServletRequest): JValue = JNothing
189203
}
204+
205+
private[spark] class DelegatingServletContextHandler(handler: ServletContextHandler) {
206+
207+
def prependFilterMapping(
208+
filterName: String,
209+
spec: String,
210+
types: EnumSet[DispatcherType]): Unit = {
211+
val mapping = new FilterMapping()
212+
mapping.setFilterName(filterName)
213+
mapping.setPathSpec(spec)
214+
mapping.setDispatcherTypes(types)
215+
handler.getServletHandler.prependFilterMapping(mapping)
216+
}
217+
218+
def addFilter(
219+
filterName: String,
220+
className: String,
221+
filterParams: Map[String, String]): Unit = {
222+
val filterHolder = new FilterHolder()
223+
filterHolder.setName(filterName)
224+
filterHolder.setClassName(className)
225+
filterParams.foreach { case (k, v) => filterHolder.setInitParameter(k, v) }
226+
handler.getServletHandler.addFilter(filterHolder)
227+
}
228+
229+
def filterCount(): Int = {
230+
handler.getServletHandler.getFilters.length
231+
}
232+
}

resource-managers/yarn/src/main/scala/org/apache/spark/scheduler/cluster/YarnSchedulerBackend.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,9 @@ private[spark] abstract class YarnSchedulerBackend(
173173
logInfo(s"Add WebUI Filter. $filterName, $filterParams, $proxyBase")
174174
conf.set("spark.ui.filters", filterName)
175175
filterParams.foreach { case (k, v) => conf.set(s"spark.$filterName.param.$k", v) }
176-
scheduler.sc.ui.foreach { ui => JettyUtils.addFilters(ui.getHandlers, conf) }
176+
scheduler.sc.ui.foreach { ui =>
177+
ui.getDelegatingHandlers.foreach(_.addFilter(filterName, filterName, filterParams))
178+
}
177179
}
178180
}
179181

0 commit comments

Comments
 (0)