feat(sparkeks): add JAR/--class entrypoint support (chipmunk EMR->EKS migration, UoW-F3) - #126
Open
prasadlohakpure wants to merge 9 commits into
Open
feat(sparkeks): add JAR/--class entrypoint support (chipmunk EMR->EKS migration, UoW-F3)#126prasadlohakpure wants to merge 9 commits into
prasadlohakpure wants to merge 9 commits into
Conversation
… migration UoW-F3) Enables the sparkeks plugin to run a custom-class (Scala/Java) Spark application via new optional jobParameters.EntryPoint + jobContext.Arguments. JAR mode sets Type:Scala/MainClass and builds args [appName, user, query, ...arguments, (resultURI)] server-side, matching com.pattern.chipmunk.Writer. SQL-wrapper path unchanged. Defensive default Spec.Type=Python guards templateless jobs. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds opt-in JAR/--class entrypoint support to the sparkeks plugin so it can launch JVM Spark applications (e.g., Chipmunk Writer) in addition to the existing SQL-wrapper path, with a defensive fallback to ensure SparkApplication.Spec.Type is never submitted empty.
Changes:
- Introduces
entry_pointandargumentsjob-context fields to enable JAR-mode SparkApplication submission. - Updates SparkApplication spec generation to support a JAR-mode argument vector and to default
Spec.Typewhen not set by templates. - Adds unit tests covering JAR mode, JAR+return_result, SQL-wrapper non-regression, and the default-Type fallback.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| internal/pkg/object/command/sparkeks/sparkeks.go | Adds JAR-mode (--class) SparkApplication configuration and a defensive default for Spec.Type. |
| internal/pkg/object/command/sparkeks/sparkeks_test.go | Adds tests validating the new JAR-mode behavior and guarding existing SQL-wrapper behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // - SQL-wrapper (Parameters.EntryPoint unset — existing behavior, byte-for-byte | ||
| // unchanged below): wrapper_uri points at a .py wrapper that reads the query from | ||
| // queryURI. | ||
| if execCtx.commandContext.WrapperURI != "" { |
| sparkApp.Spec.Arguments = []string{execCtx.appName, s3aQueryURI, execCtx.job.User, s3aResultURI} | ||
| sparkApp.Spec.MainApplicationFile = &mainAppFile | ||
|
|
||
| if jobContext.Parameters != nil && jobContext.Parameters.EntryPoint != "" { |
Extract entrypoint-specific spec (Type/MainClass/Arguments) into an entrypointStrategy interface with jarEntrypointStrategy and sqlWrapperEntrypointStrategy, selected by newEntrypointStrategy. Replaces the inline if/else in applySparkOperatorConfig. Behavior unchanged — all 4 unit tests still pass. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…dded tests Move entrypointStrategy + jar/sqlWrapper strategies + newEntrypointStrategy and jarApplicationType into internal/pkg/object/command/sparkeks/entrypoint.go. sparkeks.go keeps applySparkOperatorConfig (delegates to newEntrypointStrategy) and the Gap-4 default. Revert the added sparkeks_test.go unit tests per request. Build + vet clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…; multi JAR type - Select entrypoint strategy from wrapper_uri extension via a map (entrypointStrategiesByExt: .jar -> JAR, .py -> SQL wrapper), default SQL wrapper. - Generalize JAR application type: jarApplicationTypes map + resolveJarApplicationType, configurable via new jobParameters.ApplicationType (Scala/Java), default Scala. - Behavior-equivalent to the previous EntryPoint-based selection for all real commands; more extensible. Build + vet clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
monitorJobAndCollectLogs wrote the real error to stderr for ApplicationStateFailed, but the FailedSubmission/Unknown branch returned only a generic constant and never wrote anything to e.runtime.Stderr, silently dropping sparkApp.Status.AppState.ErrorMessage.
applySparkOperatorConfig already normalized WrapperURI, EventLogURI, queryURI, and resultURI via updateS3ToS3aURI, but merged arbitrary job/cluster properties into SparkConf verbatim. Any property value referencing a raw s3:// path (e.g. spark.kubernetes.driver.podTemplateFile) hit Hadoop's UnsupportedFileSystemException, since only s3a:// is registered without extra config.
The JAR strategy submitted [appName, user, query, ...arguments, (resultURI)] with the query inlined as literal SQL text. The deployed com.pattern.chipmunk.Writer actually takes the same shape as the Python SQL wrapper — [appName, queryURI, user, (resultURI)] — reading the SQL from the URI. Only Type/MainClass differ between the two entrypoints now. Follow-on changes: - Precompute s3aQueryURI/s3aResultURI once on executionContext instead of rewriting at each use site. - Stop blanket-rewriting s3:// -> s3a:// across all cluster/job Properties. Only keys read through Hadoop's FileSystem abstraction need s3a://, so restrict rewriting to an explicit hadoopPathProperties set (driver/executor podTemplateFile). App-specific keys such as spark.chipmunk.output.path are read by application code via the AWS SDK, which requires the literal s3:// scheme. - jobContext.Arguments is now unread by both strategies: there is no positional slot left to append to. Documented as ignored/retained for config compatibility; job-specific inputs travel as SparkConf properties. - plugins/sparkeks/README.md: document JAR/--class support — extension-based entrypoint dispatch, entry_point/application_type, the shared argument contract, and the s3:// vs s3a:// property rule. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds JAR/
--classentrypoint support to the Heimdallsparkeksplugin so it can run a custom-class(Java/Scala) Spark application, not just the built-in Python SQL wrapper. Additive and opt-in — no
existing
sparkekscommand sets a JAR wrapper, so current behavior is unchanged.Entrypoint strategy (
internal/pkg/object/command/sparkeks/entrypoint.go) — the entrypoint-specificpart of the spec (
Type/MainClass/Arguments) is dispatched behind anentrypointStrategyinterface, selected by the file extension of the command's
wrapper_uri:wrapper_uriSpec.TypeSpec.MainClass.pyPython.jarScala/Java(fromapplication_type, defaultScala)entry_pointPythonNew optional job-context fields:
parameters.entry_point(fully-qualified main class) andparameters.application_type(ScalaorJava, case-insensitive).Argument contract. Both entrypoints submit the same positional vector, matching the deployed
com.pattern.chipmunk.Writer:queryURIis ans3a://URI — the application reads the SQL from it rather than receiving it inline.Only
TypeandMainClassdiffer between the JAR and SQL-wrapper paths.s3://vss3a://in properties. Cluster/jobpropertiesare no longer blanket-rewrittens3://→s3a://. Only keys read through Hadoop'sFileSystemabstraction needs3a://, so rewritingis restricted to an explicit
hadoopPathPropertiesset (driver/executorpodTemplateFile). App-specifickeys such as
spark.chipmunk.output.pathare read by application code via the AWS SDK, which requiresthe literal
s3://scheme. Plugin-managed URIs (query, result, event log, wrapper) are still alwaysrewritten.
cluster config depends on a non-
podTemplateFileproperty being rewritten.Also in this branch: submission-failure/unknown-state reasons are now written to job stderr, and
s3aQueryURI/s3aResultURIare precomputed once on the execution context.jobContext.argumentsis retained for config compatibility but is ignored — both strategies use afixed 3/4-element vector, so there is no positional slot to append to. Job-specific inputs travel as
SparkConf properties instead.
Why
Foundation step (UoW-F3) of migrating Chipmunk's collection-build Spark jobs off EMR-on-EKS onto
Spark-on-EKS (
sparkeks). The chipmunk collection writer is a Scala JAR(
com.pattern.chipmunk.Writer);sparkekscould previously only launch the Python SQL wrapper, so itcould not run that JAR. This unlocks the
spark-chipmunk-ekscommand + operator wiring (step 4).Migration roadmap (where this PR fits)
Foundation phase. Steps 1–3 are mutually independent — none is consumed until step 4 wires them together
— so they are reviewable in parallel. Step 4 gates on all three.
snowflake-keysecret on sparkeks driver--classsupport in sparkeks pluginspark-chipmunk-ekscommand +ChipmunkCollection(use_eks=)operator (depends on 1–3)After the foundation lands: per-pipeline cutovers (
chipmunk_daily,product_catalog_chipmunk_daily,amazon_merchant_asins_daily,chipmunk_org_collection,sensors_universal,core_dims_hourly), eachadding the sparkeks path alongside EMR → validating → cutting over, with EMR removal as a separate later
PR per pipeline. Then EMR-on-EKS decommission, gated on FinOps sign-off.
Test plan
go build ./internal/... ./cmd/...— clean.go vet ./internal/pkg/object/command/sparkeks/— clean.gofmt -l internal/pkg/object/command/sparkeks/— clean.go test ./internal/pkg/object/command/sparkeks/— ok (existing package tests).The JAR argument contract was verified against the deployed chipmunk JAR by running it on the
chipmunk_eks_migration_testcollection, not by unit test.Notes / rollback
.jarwrapper_uri.The one non-additive piece is the properties-rewriting narrowing described above.
go build ./...across the whole repo reports "function main is undeclared"for every
plugins/*package — these are-buildmode=pluginpackages with nofunc main()and failthe same way on an untouched
origin/maincheckout. Not introduced by this PR.🤖 Generated with Claude Code