@@ -19,7 +19,7 @@ import (
1919)
2020
2121const (
22- defaultLaunchableViewAccess = "public "
22+ defaultLaunchableViewAccess = "organization "
2323 defaultLaunchableMode = "vm"
2424 defaultFlexibleStorageGiB = 256
2525 maxLifecycleScriptBytes = 16 * 1024
@@ -271,57 +271,102 @@ func getSelectedInstanceType(allInstanceTypes *gpusearch.AllInstanceTypesRespons
271271}
272272
273273func resolveStorageValue (instanceType gpusearch.InstanceType , requested string ) (string , error ) {
274+ requested = strings .TrimSpace (requested )
275+
274276 if len (instanceType .SupportedStorage ) == 0 {
275- if requested != "" {
276- return "" , breverrors .NewValidationError (fmt .Sprintf ("instance type %q does not expose configurable storage; omit --storage" , instanceType .Type ))
277- }
278- return "" , nil
277+ return resolveStorageWithoutSupportedStorage (instanceType .Type , requested )
279278 }
280279
281280 storage := instanceType .SupportedStorage [0 ]
282281 if storage .MinSize != "" && storage .MaxSize != "" {
283- minGiB , err := parseSizeToGiB (storage .MinSize )
284- if err != nil {
285- return "" , err
286- }
287- maxGiB , err := parseSizeToGiB (storage .MaxSize )
288- if err != nil {
289- return "" , err
290- }
282+ return resolveFlexibleStorageValue (instanceType .Type , storage , requested )
283+ }
291284
292- value := strings .TrimSpace (requested )
293- if value == "" {
294- defaultGiB := defaultFlexibleStorageGiB
295- if minGiB > 0 && defaultGiB < minGiB {
296- defaultGiB = minGiB
297- }
298- if maxGiB > 0 && defaultGiB > maxGiB {
299- defaultGiB = maxGiB
300- }
301- value = strconv .Itoa (defaultGiB )
302- }
285+ return resolveFixedStorageValue (instanceType .Type , requested )
286+ }
303287
304- sizeGiB , err := strconv .Atoi (value )
305- if err != nil || sizeGiB <= 0 {
306- return "" , breverrors .NewValidationError ("--storage must be a positive integer number of GiB" )
307- }
308- if minGiB > 0 && sizeGiB < minGiB {
309- return "" , breverrors .NewValidationError (fmt .Sprintf ("--storage must be at least %d GiB for instance type %q" , minGiB , instanceType .Type ))
310- }
311- if maxGiB > 0 && sizeGiB > maxGiB {
312- return "" , breverrors .NewValidationError (fmt .Sprintf ("--storage must be at most %d GiB for instance type %q" , maxGiB , instanceType .Type ))
313- }
288+ func resolveStorageWithoutSupportedStorage (instanceType string , requested string ) (string , error ) {
289+ if requested != "" {
290+ return "" , breverrors .NewValidationError (fmt .Sprintf ("instance type %q does not expose configurable storage; omit --storage" , instanceType ))
291+ }
314292
315- return strconv .Itoa (sizeGiB ), nil
293+ return "" , nil
294+ }
295+
296+ func resolveFlexibleStorageValue (instanceType string , storage gpusearch.Storage , requested string ) (string , error ) {
297+ minGiB , maxGiB , err := parseFlexibleStorageBounds (storage )
298+ if err != nil {
299+ return "" , err
300+ }
301+
302+ if requested == "" {
303+ return strconv .Itoa (clampDefaultFlexibleStorage (minGiB , maxGiB )), nil
304+ }
305+
306+ sizeGiB , err := parseRequestedStorageGiB (requested )
307+ if err != nil {
308+ return "" , err
309+ }
310+ if err := validateFlexibleStorageBounds (instanceType , sizeGiB , minGiB , maxGiB ); err != nil {
311+ return "" , err
316312 }
317313
314+ return strconv .Itoa (sizeGiB ), nil
315+ }
316+
317+ func resolveFixedStorageValue (instanceType string , requested string ) (string , error ) {
318318 if requested != "" {
319- return "" , breverrors .NewValidationError (fmt .Sprintf ("instance type %q uses fixed storage; omit --storage" , instanceType . Type ))
319+ return "" , breverrors .NewValidationError (fmt .Sprintf ("instance type %q uses fixed storage; omit --storage" , instanceType ))
320320 }
321321
322322 return "" , nil
323323}
324324
325+ func parseFlexibleStorageBounds (storage gpusearch.Storage ) (int , int , error ) {
326+ minGiB , err := parseSizeToGiB (storage .MinSize )
327+ if err != nil {
328+ return 0 , 0 , err
329+ }
330+ maxGiB , err := parseSizeToGiB (storage .MaxSize )
331+ if err != nil {
332+ return 0 , 0 , err
333+ }
334+
335+ return minGiB , maxGiB , nil
336+ }
337+
338+ func clampDefaultFlexibleStorage (minGiB int , maxGiB int ) int {
339+ defaultGiB := defaultFlexibleStorageGiB
340+ if minGiB > 0 && defaultGiB < minGiB {
341+ defaultGiB = minGiB
342+ }
343+ if maxGiB > 0 && defaultGiB > maxGiB {
344+ defaultGiB = maxGiB
345+ }
346+
347+ return defaultGiB
348+ }
349+
350+ func parseRequestedStorageGiB (requested string ) (int , error ) {
351+ sizeGiB , err := strconv .Atoi (requested )
352+ if err != nil || sizeGiB <= 0 {
353+ return 0 , breverrors .NewValidationError ("--storage must be a positive integer number of GiB" )
354+ }
355+
356+ return sizeGiB , nil
357+ }
358+
359+ func validateFlexibleStorageBounds (instanceType string , sizeGiB int , minGiB int , maxGiB int ) error {
360+ if minGiB > 0 && sizeGiB < minGiB {
361+ return breverrors .NewValidationError (fmt .Sprintf ("--storage must be at least %d GiB for instance type %q" , minGiB , instanceType ))
362+ }
363+ if maxGiB > 0 && sizeGiB > maxGiB {
364+ return breverrors .NewValidationError (fmt .Sprintf ("--storage must be at most %d GiB for instance type %q" , maxGiB , instanceType ))
365+ }
366+
367+ return nil
368+ }
369+
325370func resolveLifecycleScript (opts launchableCreateOptions ) (string , error ) {
326371 if opts .Mode != "vm" {
327372 return "" , nil
@@ -408,33 +453,59 @@ func parseSecureLinks(rawLinks []string) ([]secureLinkSpec, error) {
408453 }
409454
410455 links := make ([]secureLinkSpec , 0 , len (rawLinks ))
411- nameSet := map [string ]struct {}{}
412- ctaCount := 0
456+ state := newSecureLinkValidationState ()
413457
414458 for _ , raw := range rawLinks {
415459 link , err := parseSecureLink (raw )
416460 if err != nil {
417461 return nil , err
418462 }
419- if _ , exists := nameSet [link .Name ]; exists {
420- return nil , breverrors .NewValidationError (fmt .Sprintf ("duplicate secure link name %q" , link .Name ))
421- }
422-
423- nameSet [link .Name ] = struct {}{}
424- if link .CTA {
425- ctaCount ++
463+ if err := state .add (link ); err != nil {
464+ return nil , err
426465 }
427466
428467 links = append (links , link )
429468 }
430469
431- if ctaCount > maxCTAServiceCount {
432- return nil , breverrors . NewValidationError ( fmt . Sprintf ( "at most %d secure links can have cta=true" , maxCTAServiceCount ))
470+ if err := state . validate (); err != nil {
471+ return nil , err
433472 }
434473
435474 return links , nil
436475}
437476
477+ type secureLinkValidationState struct {
478+ nameSet map [string ]struct {}
479+ ctaCount int
480+ }
481+
482+ func newSecureLinkValidationState () secureLinkValidationState {
483+ return secureLinkValidationState {
484+ nameSet : map [string ]struct {}{},
485+ }
486+ }
487+
488+ func (s * secureLinkValidationState ) add (link secureLinkSpec ) error {
489+ if _ , exists := s .nameSet [link .Name ]; exists {
490+ return breverrors .NewValidationError (fmt .Sprintf ("duplicate secure link name %q" , link .Name ))
491+ }
492+
493+ s .nameSet [link .Name ] = struct {}{}
494+ if link .CTA {
495+ s .ctaCount ++
496+ }
497+
498+ return nil
499+ }
500+
501+ func (s secureLinkValidationState ) validate () error {
502+ if s .ctaCount > maxCTAServiceCount {
503+ return breverrors .NewValidationError (fmt .Sprintf ("at most %d secure links can have cta=true" , maxCTAServiceCount ))
504+ }
505+
506+ return nil
507+ }
508+
438509func parseSecureLink (raw string ) (secureLinkSpec , error ) {
439510 values , err := parseFlagAssignments (raw )
440511 if err != nil {
0 commit comments