11//! This module provides the SparkApplicationTemplateSpec CRD definition.
22
3- use std:: { collections :: HashMap , num:: ParseIntError , str:: ParseBoolError } ;
3+ use std:: { num:: ParseIntError , str:: ParseBoolError } ;
44
55use regex:: Regex ;
66use serde:: { Deserialize , Serialize } ;
77use snafu:: { ResultExt , Snafu } ;
88use stackable_operator:: {
9- commons:: product_image_selection:: ProductImage ,
10- crd:: s3,
11- k8s_openapi:: api:: core:: v1:: { EnvVar , Volume } ,
129 kube:: { Api , CustomResource , ResourceExt , api:: ListParams } ,
1310 schemars:: { self , JsonSchema } ,
14- utils:: crds:: raw_object_list_schema,
1511 versioned:: versioned,
1612} ;
1713use strum:: { EnumDiscriminants , IntoStaticStr } ;
1814
19- use super :: {
20- SparkApplicationDriverRoleType , SparkApplicationExecutorRoleType , SparkApplicationJobRoleType ,
21- history:: LogFileDirectorySpec , job_dependencies:: JobDependencies , roles:: SparkMode ,
22- } ;
2315use crate :: crd:: template_merger:: deep_merge;
2416
2517#[ derive( Snafu , Debug , EnumDiscriminants ) ]
@@ -77,85 +69,11 @@ pub mod versioned {
7769 #[ derive( Clone , CustomResource , Debug , Deserialize , JsonSchema , Serialize ) ]
7870 #[ serde( rename_all = "camelCase" ) ]
7971 pub struct SparkApplicationTemplateSpec {
80- /// Mode: cluster or client. Currently only cluster is supported.
81- pub mode : SparkMode ,
82-
83- /// The main class - i.e. entry point - for JVM artifacts.
84- #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
85- pub main_class : Option < String > ,
86-
87- /// The actual application file that will be called by `spark-submit`.
88- pub main_application_file : String ,
89-
90- /// User-supplied image containing spark-job dependencies that will be copied to the specified volume mount.
91- /// See the [examples](DOCS_BASE_URL_PLACEHOLDER/spark-k8s/usage-guide/examples).
92- #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
93- pub image : Option < String > ,
94-
95- // no doc - docs in ProductImage struct.
96- pub spark_image : ProductImage ,
97-
98- /// Name of the Vector aggregator [discovery ConfigMap](DOCS_BASE_URL_PLACEHOLDER/concepts/service_discovery).
99- /// It must contain the key `ADDRESS` with the address of the Vector aggregator.
100- /// Follow the [logging tutorial](DOCS_BASE_URL_PLACEHOLDER/tutorials/logging-vector-aggregator)
101- /// to learn how to configure log aggregation with Vector.
102- #[ serde( skip_serializing_if = "Option::is_none" ) ]
103- pub vector_aggregator_config_map_name : Option < String > ,
104-
105- /// The job builds a spark-submit command, complete with arguments and referenced dependencies
106- /// such as templates, and passes it on to Spark.
107- /// The reason this property uses its own type (SubmitConfigFragment) is because logging is not
108- /// supported for spark-submit processes.
109- //
110- // IMPORTANT: Please note that the jvmArgumentOverrides have no effect here!
111- // However, due to product-config things I wasn't able to remove them.
112- #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
113- pub job : Option < SparkApplicationJobRoleType > ,
114-
115- /// The driver role specifies the configuration that, together with the driver pod template, is used by
116- /// Spark to create driver pods.
117- #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
118- pub driver : Option < SparkApplicationDriverRoleType > ,
119-
120- /// The executor role specifies the configuration that, together with the driver pod template, is used by
121- /// Spark to create the executor pods.
122- /// This is RoleGroup instead of plain CommonConfiguration because it needs to allow for the number of replicas.
123- /// to be specified.
124- #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
125- pub executor : Option < SparkApplicationExecutorRoleType > ,
126-
127- /// A map of key/value strings that will be passed directly to spark-submit.
128- #[ serde( default ) ]
129- pub spark_conf : HashMap < String , String > ,
130-
131- /// Job dependencies: a list of python packages that will be installed via pip, a list of packages
132- /// or repositories that is passed directly to spark-submit, or a list of excluded packages
133- /// (also passed directly to spark-submit).
134- #[ serde( default ) ]
135- pub deps : JobDependencies ,
136-
137- /// Configure an S3 connection that the SparkApplication has access to.
138- /// Read more in the [Spark S3 usage guide](DOCS_BASE_URL_PLACEHOLDER/spark-k8s/usage-guide/s3).
139- #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
140- pub s3connection : Option < s3:: v1alpha1:: InlineConnectionOrReference > ,
141-
142- /// Arguments passed directly to the job artifact.
143- #[ serde( default ) ]
144- pub args : Vec < String > ,
145-
146- /// A list of volumes that can be made available to the job, driver or executors via their volume mounts.
147- #[ serde( default ) ]
148- #[ schemars( schema_with = "raw_object_list_schema" ) ]
149- pub volumes : Vec < Volume > ,
150-
151- /// A list of environment variables that will be set in the job pod and the driver and executor
152- /// pod templates.
153- #[ serde( default ) ]
154- pub env : Vec < EnvVar > ,
155-
156- /// The log file directory definition used by the Spark history server.
157- #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
158- pub log_file_directory : Option < LogFileDirectorySpec > ,
72+ /// The template body mirrors a [`SparkApplication`](super::super::v1alpha1::SparkApplication)
73+ /// spec exactly — it is merged into a `SparkApplication` at reconcile time, see
74+ /// [`merge_application_templates`].
75+ #[ serde( flatten) ]
76+ pub spec : crate :: crd:: v1alpha1:: SparkApplicationSpec ,
15977 }
16078}
16179
@@ -170,33 +88,11 @@ impl From<&v1alpha1::SparkApplicationTemplate>
17088 }
17189}
17290
173- impl From < & v1alpha1:: SparkApplicationTemplate > for super :: v1alpha1:: SparkApplication {
174- fn from ( template : & v1alpha1:: SparkApplicationTemplate ) -> super :: v1alpha1:: SparkApplication {
175- let spec = super :: v1alpha1:: SparkApplicationSpec {
176- mode : template. spec . mode . clone ( ) ,
177- main_class : template. spec . main_class . clone ( ) ,
178- main_application_file : template. spec . main_application_file . clone ( ) ,
179- image : template. spec . image . clone ( ) ,
180- spark_image : template. spec . spark_image . clone ( ) ,
181- vector_aggregator_config_map_name : template
182- . spec
183- . vector_aggregator_config_map_name
184- . clone ( ) ,
185- job : template. spec . job . clone ( ) ,
186- driver : template. spec . driver . clone ( ) ,
187- executor : template. spec . executor . clone ( ) ,
188- spark_conf : template. spec . spark_conf . clone ( ) ,
189- deps : template. spec . deps . clone ( ) ,
190- s3connection : template. spec . s3connection . clone ( ) ,
191- args : template. spec . args . clone ( ) ,
192- volumes : template. spec . volumes . clone ( ) ,
193- env : template. spec . env . clone ( ) ,
194- log_file_directory : template. spec . log_file_directory . clone ( ) ,
195- } ;
196-
91+ impl From < v1alpha1:: SparkApplicationTemplate > for super :: v1alpha1:: SparkApplication {
92+ fn from ( template : v1alpha1:: SparkApplicationTemplate ) -> super :: v1alpha1:: SparkApplication {
19793 super :: v1alpha1:: SparkApplication {
198- metadata : template. metadata . clone ( ) ,
199- spec,
94+ metadata : template. metadata ,
95+ spec : template . spec . spec ,
20096 status : None ,
20197 }
20298 }
@@ -379,6 +275,7 @@ pub(crate) async fn merge_application_templates(
379275 // which has the highest priority during merging.
380276 let mut template_apps: Vec < super :: v1alpha1:: SparkApplication > = templates
381277 . iter ( )
278+ . cloned ( )
382279 . map ( super :: v1alpha1:: SparkApplication :: from)
383280 . collect :: < Vec < super :: v1alpha1:: SparkApplication > > ( ) ;
384281 template_apps. push ( spark_application. clone ( ) ) ;
0 commit comments