@@ -366,9 +366,10 @@ func validateLicensesFromImages(ctx context.Context, rt runtime.Runtime, sink ou
366366func startContainers (ctx context.Context , rt runtime.Runtime , sink output.Sink , tel * telemetry.Client , containers []runtime.ContainerConfig , pulled map [string ]bool ) error {
367367 for _ , c := range containers {
368368 startTime := time .Now ()
369- sink .Emit (output.ContainerStatusEvent { Phase : "starting" , Container : c . Name } )
369+ sink .Emit (output .SpinnerStart ( "Starting LocalStack" ) )
370370 containerID , err := rt .Start (ctx , c )
371371 if err != nil {
372+ sink .Emit (output .SpinnerStop ())
372373 tel .EmitEmulatorLifecycleEvent (ctx , telemetry.LifecycleEvent {
373374 EventType : telemetry .LifecycleStartError ,
374375 Emulator : c .EmulatorType ,
@@ -379,9 +380,9 @@ func startContainers(ctx context.Context, rt runtime.Runtime, sink output.Sink,
379380 return fmt .Errorf ("failed to start LocalStack: %w" , err )
380381 }
381382
382- sink .Emit (output.ContainerStatusEvent {Phase : "waiting" , Container : c .Name })
383383 healthURL := fmt .Sprintf ("http://localhost:%s%s" , c .Port , c .HealthPath )
384384 if err := awaitStartup (ctx , rt , sink , containerID , "LocalStack" , healthURL ); err != nil {
385+ sink .Emit (output .SpinnerStop ())
385386 errCode := telemetry .ErrCodeStartFailed
386387 var licErr * licenseNotCoveredError
387388 if errors .As (err , & licErr ) && c .EmulatorType == config .EmulatorSnowflake {
@@ -404,6 +405,7 @@ func startContainers(ctx context.Context, rt runtime.Runtime, sink output.Sink,
404405 })
405406 return err
406407 }
408+ sink .Emit (output .SpinnerStop ())
407409
408410 sink .Emit (output.ContainerStatusEvent {Phase : "ready" , Container : c .Name , Detail : fmt .Sprintf ("containerId: %s" , containerID [:12 ])})
409411
@@ -549,7 +551,7 @@ func emitPortInUseError(sink output.Sink, port string) {
549551
550552func validateLicense (ctx context.Context , sink output.Sink , opts StartOptions , containerConfig runtime.ContainerConfig , token , licenseFilePath string ) error {
551553 version := containerConfig .Tag
552- sink .Emit (output.ContainerStatusEvent { Phase : "validating license", Container : containerConfig . Name } )
554+ sink .Emit (output .SpinnerStart ( "Checking license") )
553555
554556 hostname , _ := os .Hostname ()
555557 licenseReq := & api.LicenseRequest {
@@ -569,6 +571,7 @@ func validateLicense(ctx context.Context, sink output.Sink, opts StartOptions, c
569571
570572 licenseResp , err := opts .PlatformClient .GetLicense (ctx , licenseReq )
571573 if err != nil {
574+ sink .Emit (output .SpinnerStop ())
572575 var licErr * api.LicenseError
573576 if errors .As (err , & licErr ) && licErr .Detail != "" {
574577 opts .Logger .Error ("license server response (HTTP %d): %s" , licErr .Status , licErr .Detail )
@@ -582,6 +585,13 @@ func validateLicense(ctx context.Context, sink output.Sink, opts StartOptions, c
582585 })
583586 return fmt .Errorf ("license validation failed for %s:%s: %w" , containerConfig .ProductName , version , err )
584587 }
588+ sink .Emit (output .SpinnerStop ())
589+
590+ validMsg := "Valid license"
591+ if plan := licenseResp .PlanDisplayName (); plan != "" {
592+ validMsg = fmt .Sprintf ("Valid license (%s)" , plan )
593+ }
594+ sink .Emit (output.MessageEvent {Severity : output .SeveritySuccess , Text : validMsg })
585595
586596 if licenseResp != nil && len (licenseResp .RawBytes ) > 0 {
587597 if err := os .MkdirAll (filepath .Dir (licenseFilePath ), 0755 ); err != nil {
0 commit comments