Skip to content

Commit c2ce137

Browse files
committed
refactor: consolidate error handling
1 parent 397471b commit c2ce137

6 files changed

Lines changed: 114 additions & 78 deletions

File tree

rust/operator-binary/src/spark_k8s_controller.rs

Lines changed: 4 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use std::sync::Arc;
22

33
use snafu::{ResultExt, Snafu};
44
use stackable_operator::{
5-
builder::{self},
65
k8s_openapi::api::{
76
batch::v1::Job,
87
core::v1::{ConfigMap, ServiceAccount},
@@ -15,13 +14,12 @@ use stackable_operator::{
1514
},
1615
logging::controller::ReconcilerError,
1716
shared::time::Duration,
18-
v2::config_file_writer::PropertiesWriterError,
1917
};
2018
use strum::{EnumDiscriminants, IntoStaticStr};
2119

2220
use crate::{
2321
Ctx,
24-
crd::{constants::*, roles::SparkApplicationRole, v1alpha1},
22+
crd::{constants::*, v1alpha1},
2523
};
2624

2725
pub mod build;
@@ -38,8 +36,8 @@ pub enum Error {
3836
#[snafu(display("failed to validate SparkApplication"))]
3937
ValidateSparkApplication { source: validate::Error },
4038

41-
#[snafu(display("missing secret lifetime"))]
42-
MissingSecretLifetime,
39+
#[snafu(display("failed to build SparkApplication resources"))]
40+
BuildSparkApplication { source: build::Error },
4341

4442
#[snafu(display("failed to apply role ServiceAccount"))]
4543
ApplyServiceAccount {
@@ -56,54 +54,12 @@ pub enum Error {
5654
source: stackable_operator::client::Error,
5755
},
5856

59-
#[snafu(display("failed to build stark-submit command"))]
60-
BuildCommand { source: crate::crd::Error },
61-
62-
#[snafu(display("failed to build the pod template config map"))]
63-
PodTemplateConfigMap {
64-
source: stackable_operator::builder::configmap::Error,
65-
},
66-
67-
#[snafu(display("pod template serialization"))]
68-
PodTemplateSerde { source: serde_yaml::Error },
69-
70-
#[snafu(display("failed to resolve and merge config"))]
71-
FailedToResolveConfig { source: crate::crd::Error },
72-
73-
#[snafu(display("vector agent is enabled but vector aggregator ConfigMap is missing"))]
74-
VectorAggregatorConfigMapMissing,
75-
76-
#[snafu(display("failed to validate the logging configuration"))]
77-
ValidateLoggingConfig {
78-
source: stackable_operator::v2::product_logging::framework::Error,
79-
},
80-
81-
#[snafu(display("failed to serialize [{JVM_SECURITY_PROPERTIES_FILE}] for {}", role))]
82-
JvmSecurityProperties {
83-
source: PropertiesWriterError,
84-
role: SparkApplicationRole,
85-
},
86-
87-
#[snafu(display("invalid submit config"))]
88-
SubmitConfig { source: crate::crd::Error },
89-
90-
#[snafu(display("failed to create Volumes for SparkApplication"))]
91-
CreateVolumes { source: crate::crd::Error },
92-
9357
#[snafu(display("Failed to update status for application {name:?}"))]
9458
ApplySparkApplicationStatus {
9559
source: stackable_operator::client::Error,
9660
name: String,
9761
},
9862

99-
#[snafu(display("failed to add needed volume"))]
100-
AddVolume { source: builder::pod::Error },
101-
102-
#[snafu(display("failed to add needed volumeMount"))]
103-
AddVolumeMount {
104-
source: builder::pod::container::Error,
105-
},
106-
10763
#[snafu(display("SparkApplication object is invalid"))]
10864
InvalidSparkApplication {
10965
// boxed because otherwise Clippy warns about a large enum variant
@@ -168,7 +124,7 @@ pub async fn reconcile(
168124
// No more mutating operations after this point (except for status).
169125
tracing::debug!("reconciling spark application [{spark_application:?}]");
170126

171-
let resources = build::build(&validated)?;
127+
let resources = build::build(&validated).context(BuildSparkApplicationSnafu)?;
172128

173129
// Apply the ServiceAccount and RoleBinding first, then the ConfigMaps, and finally the Job:
174130
// the Job runs under the ServiceAccount and mounts the ConfigMaps, so they must exist first.

rust/operator-binary/src/spark_k8s_controller/build/mod.rs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,34 @@
11
pub mod pod;
22
pub mod resource;
33

4-
use snafu::ResultExt;
4+
use resource::{config_map, job};
5+
use snafu::{ResultExt, Snafu};
56

67
use crate::{
78
crd::roles::SparkApplicationRole,
8-
spark_k8s_controller::{
9-
BuildCommandSnafu, FailedToResolveConfigSnafu, Result, SparkResources, SubmitConfigSnafu,
10-
validate::ValidatedSparkApplication,
11-
},
9+
spark_k8s_controller::{SparkResources, validate::ValidatedSparkApplication},
1210
};
1311

12+
#[derive(Snafu, Debug)]
13+
pub enum Error {
14+
#[snafu(display("failed to resolve and merge config"))]
15+
FailedToResolveConfig { source: crate::crd::Error },
16+
17+
#[snafu(display("failed to build stark-submit command"))]
18+
BuildCommand { source: crate::crd::Error },
19+
20+
#[snafu(display("invalid submit config"))]
21+
SubmitConfig { source: crate::crd::Error },
22+
23+
#[snafu(display("failed to build ConfigMap"))]
24+
BuildConfigMap { source: config_map::Error },
25+
26+
#[snafu(display("failed to build Job"))]
27+
BuildJob { source: job::Error },
28+
}
29+
30+
type Result<T, E = Error> = std::result::Result<T, E>;
31+
1432
/// Builds every Kubernetes resource for the given validated SparkApplication.
1533
pub fn build(validated: &ValidatedSparkApplication) -> Result<SparkResources> {
1634
let spark_application = &validated.spark_application;
@@ -19,7 +37,7 @@ pub fn build(validated: &ValidatedSparkApplication) -> Result<SparkResources> {
1937
let resolved_product_image = &validated.resolved_product_image;
2038

2139
let (service_account, role_binding) =
22-
resource::serviceaccount::build_spark_role_serviceaccount(validated)?;
40+
resource::serviceaccount::build_spark_role_serviceaccount(validated);
2341

2442
let env_vars = spark_application.env(opt_s3conn, logdir);
2543

@@ -41,7 +59,8 @@ pub fn build(validated: &ValidatedSparkApplication) -> Result<SparkResources> {
4159
&driver_config_overrides,
4260
&env_vars,
4361
&service_account,
44-
)?;
62+
)
63+
.context(BuildConfigMapSnafu)?;
4564

4665
let executor_config = spark_application
4766
.executor_config()
@@ -61,7 +80,8 @@ pub fn build(validated: &ValidatedSparkApplication) -> Result<SparkResources> {
6180
&executor_config_overrides,
6281
&env_vars,
6382
&service_account,
64-
)?;
83+
)
84+
.context(BuildConfigMapSnafu)?;
6585

6686
let job_commands = spark_application
6787
.build_command(opt_s3conn, logdir, &resolved_product_image.image)
@@ -79,15 +99,17 @@ pub fn build(validated: &ValidatedSparkApplication) -> Result<SparkResources> {
7999
.unwrap_or_default();
80100

81101
let submit_job_config_map =
82-
resource::config_map::submit_job_config_map(validated, &submit_config_overrides)?;
102+
resource::config_map::submit_job_config_map(validated, &submit_config_overrides)
103+
.context(BuildConfigMapSnafu)?;
83104

84105
let job = resource::job::spark_job(
85106
validated,
86107
&service_account,
87108
&env_vars,
88109
&job_commands,
89110
&submit_config,
90-
)?;
111+
)
112+
.context(BuildJobSnafu)?;
91113

92114
Ok(SparkResources {
93115
service_account,

rust/operator-binary/src/spark_k8s_controller/build/pod.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::str::FromStr;
22

3-
use snafu::{OptionExt, ResultExt};
3+
use snafu::{OptionExt, ResultExt, Snafu};
44
use stackable_operator::{
55
builder::{
66
meta::ObjectMetaBuilder,
@@ -38,12 +38,32 @@ use crate::{
3838
roles::{RoleConfig, SparkApplicationRole, SparkContainer},
3939
tlscerts,
4040
},
41-
spark_k8s_controller::{
42-
AddVolumeMountSnafu, AddVolumeSnafu, Result, ValidateLoggingConfigSnafu,
43-
VectorAggregatorConfigMapMissingSnafu, validate,
44-
},
41+
spark_k8s_controller::validate,
4542
};
4643

44+
#[derive(Snafu, Debug)]
45+
pub enum Error {
46+
#[snafu(display("failed to add needed volumeMount"))]
47+
AddVolumeMount {
48+
source: stackable_operator::builder::pod::container::Error,
49+
},
50+
51+
#[snafu(display("failed to add needed volume"))]
52+
AddVolume {
53+
source: stackable_operator::builder::pod::Error,
54+
},
55+
56+
#[snafu(display("failed to validate the logging configuration"))]
57+
ValidateLoggingConfig {
58+
source: stackable_operator::v2::product_logging::framework::Error,
59+
},
60+
61+
#[snafu(display("vector agent is enabled but vector aggregator ConfigMap is missing"))]
62+
VectorAggregatorConfigMapMissing,
63+
}
64+
65+
type Result<T, E = Error> = std::result::Result<T, E>;
66+
4767
fn init_containers(
4868
validated: &validate::ValidatedSparkApplication,
4969
logging: &Logging<SparkContainer>,

rust/operator-binary/src/spark_k8s_controller/build/resource/config_map.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use snafu::{OptionExt, ResultExt};
1+
use snafu::{OptionExt, ResultExt, Snafu};
22
use stackable_operator::{
33
builder::{configmap::ConfigMapBuilder, pod::volume::VolumeBuilder},
44
k8s_openapi::api::core::v1::{ConfigMap, EnvVar, ServiceAccount},
@@ -20,12 +20,39 @@ use crate::{
2020
},
2121
product_logging::{self},
2222
spark_k8s_controller::{
23-
CreateVolumesSnafu, JvmSecurityPropertiesSnafu, MissingSecretLifetimeSnafu,
24-
PodTemplateConfigMapSnafu, PodTemplateSerdeSnafu, Result, build::pod::pod_template,
23+
build::pod::{self, pod_template},
2524
validate,
2625
},
2726
};
2827

28+
#[derive(Snafu, Debug)]
29+
pub enum Error {
30+
#[snafu(display("failed to build the pod template"))]
31+
BuildPodTemplate { source: pod::Error },
32+
33+
#[snafu(display("pod template serialization"))]
34+
PodTemplateSerde { source: serde_yaml::Error },
35+
36+
#[snafu(display("failed to serialize [{JVM_SECURITY_PROPERTIES_FILE}] for {}", role))]
37+
JvmSecurityProperties {
38+
source: stackable_operator::v2::config_file_writer::PropertiesWriterError,
39+
role: SparkApplicationRole,
40+
},
41+
42+
#[snafu(display("failed to build the pod template config map"))]
43+
PodTemplateConfigMap {
44+
source: stackable_operator::builder::configmap::Error,
45+
},
46+
47+
#[snafu(display("missing secret lifetime"))]
48+
MissingSecretLifetime,
49+
50+
#[snafu(display("failed to create Volumes for SparkApplication"))]
51+
CreateVolumes { source: crate::crd::Error },
52+
}
53+
54+
type Result<T, E = Error> = std::result::Result<T, E>;
55+
2956
pub(crate) fn pod_template_config_map(
3057
validated: &validate::ValidatedSparkApplication,
3158
role: SparkApplicationRole,
@@ -75,7 +102,8 @@ pub(crate) fn pod_template_config_map(
75102
volumes.as_ref(),
76103
env,
77104
service_account,
78-
)?;
105+
)
106+
.context(BuildPodTemplateSnafu)?;
79107

80108
let mut cm_builder = ConfigMapBuilder::new();
81109

rust/operator-binary/src/spark_k8s_controller/build/resource/job.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use snafu::{OptionExt, ResultExt};
1+
use snafu::{OptionExt, ResultExt, Snafu};
22
use stackable_operator::{
33
builder::{meta::ObjectMetaBuilder, pod::volume::VolumeBuilder},
44
k8s_openapi::{
@@ -17,12 +17,25 @@ use crate::{
1717
roles::{SparkApplicationRole, SparkContainer, SubmitConfig},
1818
tlscerts,
1919
},
20-
spark_k8s_controller::{
21-
AddVolumeMountSnafu, CreateVolumesSnafu, MissingSecretLifetimeSnafu, Result,
22-
build::pod::security_context, validate,
23-
},
20+
spark_k8s_controller::{build::pod::security_context, validate},
2421
};
2522

23+
#[derive(Snafu, Debug)]
24+
pub enum Error {
25+
#[snafu(display("failed to add needed volumeMount"))]
26+
AddVolumeMount {
27+
source: stackable_operator::builder::pod::container::Error,
28+
},
29+
30+
#[snafu(display("missing secret lifetime"))]
31+
MissingSecretLifetime,
32+
33+
#[snafu(display("failed to create Volumes for SparkApplication"))]
34+
CreateVolumes { source: crate::crd::Error },
35+
}
36+
37+
type Result<T, E = Error> = std::result::Result<T, E>;
38+
2639
pub(crate) fn spark_job(
2740
validated: &validate::ValidatedSparkApplication,
2841
serviceaccount: &ServiceAccount,

rust/operator-binary/src/spark_k8s_controller/build/resource/serviceaccount.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,15 @@ use stackable_operator::k8s_openapi::{
66
},
77
};
88

9-
use crate::{
10-
crd::constants::*,
11-
spark_k8s_controller::{Result, validate},
12-
};
9+
use crate::{crd::constants::*, spark_k8s_controller::validate};
1310

1411
/// For a given SparkApplication, we create a ServiceAccount with a RoleBinding to the ClusterRole
1512
/// that allows the driver to create pods etc.
1613
/// Both objects have an owner reference to the SparkApplication, as well as the same name as the app.
1714
/// They are deleted when the job is deleted.
1815
pub(crate) fn build_spark_role_serviceaccount(
1916
validated: &validate::ValidatedSparkApplication,
20-
) -> Result<(ServiceAccount, RoleBinding)> {
17+
) -> (ServiceAccount, RoleBinding) {
2118
let sa_name = validated.name.to_string();
2219
let sa = ServiceAccount {
2320
metadata: validated.object_meta(&sa_name, "service-account").build(),
@@ -38,5 +35,5 @@ pub(crate) fn build_spark_role_serviceaccount(
3835
namespace: sa.metadata.namespace.clone(),
3936
}]),
4037
};
41-
Ok((sa, binding))
38+
(sa, binding)
4239
}

0 commit comments

Comments
 (0)