11/*
2- Copyright 2024-2025 The Spice.ai OSS Authors
2+ Copyright 2024-2026 The Spice.ai OSS Authors
33
44Licensed under the Apache License, Version 2.0 (the "License");
55you may not use this file except in compliance with the License.
@@ -34,11 +34,13 @@ pub(crate) struct AppCreateConfig {
3434 pub app_cpu_request : Option < String > ,
3535 pub app_memory_request : Option < String > ,
3636 pub app_replicas : Option < i32 > ,
37+ pub app_storage_size_gb : Option < f64 > ,
3738 pub executor_replicas : i32 ,
3839 pub executor_memory_limit : Option < String > ,
3940 pub executor_cpu_limit : Option < String > ,
4041 pub executor_cpu_request : Option < String > ,
4142 pub executor_memory_request : Option < String > ,
43+ pub executor_storage_size_gb : Option < f64 > ,
4244}
4345
4446pub ( crate ) fn spice_cloud_base_url ( api_url_override : Option < & str > ) -> String {
@@ -167,6 +169,7 @@ pub(crate) async fn ensure_spice_cloud_app(
167169 config. executor_cpu_request . as_deref ( ) ,
168170 config. executor_memory_request . as_deref ( ) ,
169171 ) ) ,
172+ storage_size_gb : config. executor_storage_size_gb ,
170173 } ) ;
171174
172175 let create_result = cloud
@@ -186,11 +189,15 @@ pub(crate) async fn ensure_spice_cloud_app(
186189 . await ;
187190
188191 match create_result {
189- Ok ( app) => Ok ( app. id ) ,
192+ Ok ( app) => {
193+ apply_storage_config ( cloud, app. id , config) . await ?;
194+ Ok ( app. id )
195+ }
190196 Err ( spice_cloud_client:: error:: Error :: Conflict { .. } ) => {
191197 // Race condition — another caller created it; re-fetch
192198 let apps = cloud. list_apps ( ) . await ?;
193199 if let Some ( app) = apps. into_iter ( ) . find ( |a| a. name == app_name) {
200+ apply_storage_config ( cloud, app. id , config) . await ?;
194201 return Ok ( app. id ) ;
195202 }
196203 Err ( anyhow:: anyhow!(
@@ -203,6 +210,46 @@ pub(crate) async fn ensure_spice_cloud_app(
203210 }
204211}
205212
213+ /// Apply storage configuration to an app via the update API if any storage
214+ /// sizes are configured.
215+ async fn apply_storage_config (
216+ cloud : & CloudClient ,
217+ app_id : i64 ,
218+ config : & AppCreateConfig ,
219+ ) -> anyhow:: Result < ( ) > {
220+ let has_storage =
221+ config. app_storage_size_gb . is_some ( ) || config. executor_storage_size_gb . is_some ( ) ;
222+
223+ if !has_storage {
224+ return Ok ( ( ) ) ;
225+ }
226+
227+ let executor = config. executor_storage_size_gb . map ( |size| AppExecutor {
228+ replicas : None ,
229+ resources : None ,
230+ storage_size_gb : Some ( size) ,
231+ } ) ;
232+
233+ cloud
234+ . update_app (
235+ app_id,
236+ & UpdateAppRequest {
237+ description : None ,
238+ visibility : None ,
239+ replicas : None ,
240+ image_tag : None ,
241+ region : None ,
242+ spicepod : None ,
243+ resources : None ,
244+ executor,
245+ storage_size_gb : config. app_storage_size_gb ,
246+ } ,
247+ )
248+ . await ?;
249+
250+ Ok ( ( ) )
251+ }
252+
206253pub ( crate ) async fn resolve_default_cname ( cloud : & CloudClient ) -> anyhow:: Result < String > {
207254 let regions = cloud. list_regions ( None ) . await ?;
208255
@@ -259,6 +306,7 @@ pub(crate) async fn apply_spicepod_to_app(
259306 spicepod : Some ( spicepod_yaml. to_string ( ) ) ,
260307 resources : None ,
261308 executor : None ,
309+ storage_size_gb : None ,
262310 } ,
263311 )
264312 . await ?;
0 commit comments