@@ -3,6 +3,8 @@ package cmd
33import (
44 "fmt"
55 "log"
6+ "net/http"
7+ "time"
68
79 "github.com/microcks/microcks-cli/pkg/config"
810 "github.com/microcks/microcks-cli/pkg/connectors"
@@ -12,11 +14,13 @@ import (
1214
1315func NewStartCommand (globalClientOpts * connectors.ClientOptions ) * cobra.Command {
1416 var (
15- name string
16- hostPort string
17- imageName string
18- autoRemove bool
19- driver string
17+ name string
18+ hostPort string
19+ imageName string
20+ autoRemove bool
21+ driver string
22+ readyTimeout time.Duration
23+ noWait bool
2024 )
2125 var startCmd = & cobra.Command {
2226 Use : "start" ,
@@ -140,6 +144,17 @@ microcks start --name [name of you container/instance]`,
140144 err = config .WriteLocalConfig (* localConfig , configFile )
141145 errors .CheckError (err )
142146
147+ // The container being up doesn't mean the Microcks server inside
148+ // is serving traffic yet: wait until HTTP is actually answering
149+ // so chained commands (import, test) don't race the boot.
150+ if ! noWait {
151+ fmt .Printf ("Waiting for Microcks to be ready at %s ...\n " , server )
152+ if err := waitForReady (server , readyTimeout ); err != nil {
153+ log .Fatalf ("Microcks container is started but the server is not ready: %v. " +
154+ "It may still be booting — retry shortly or raise --ready-timeout." , err )
155+ }
156+ }
157+
143158 fmt .Printf ("Microcks started successfully at %s\n " , server )
144159 },
145160 }
@@ -148,5 +163,28 @@ microcks start --name [name of you container/instance]`,
148163 startCmd .Flags ().StringVar (& imageName , "image" , "quay.io/microcks/microcks-uber:latest-native" , "image which will be used to create a container" )
149164 startCmd .Flags ().BoolVar (& autoRemove , "rm" , false , "mimic of '--rm' flag of Docker to automatically remove the container when it exits" )
150165 startCmd .Flags ().StringVar (& driver , "driver" , "docker" , "use --driver to change driver from docker to podman" )
166+ startCmd .Flags ().DurationVar (& readyTimeout , "ready-timeout" , 60 * time .Second , "how long to wait for the Microcks server to be ready before failing" )
167+ startCmd .Flags ().BoolVar (& noWait , "no-wait" , false , "return as soon as the container is started, without waiting for the Microcks server to be ready" )
151168 return startCmd
152169}
170+
171+ // waitForReady polls the Microcks API until it answers with 200 or the
172+ // timeout elapses. HTTP being up is the signal users care about — the
173+ // Spring Boot app inside the container takes a while after the container
174+ // process itself is running.
175+ func waitForReady (serverURL string , timeout time.Duration ) error {
176+ url := serverURL + "/api/keycloak/config"
177+ httpClient := & http.Client {Timeout : 2 * time .Second }
178+ deadline := time .Now ().Add (timeout )
179+ for time .Now ().Before (deadline ) {
180+ resp , err := httpClient .Get (url )
181+ if err == nil {
182+ resp .Body .Close ()
183+ if resp .StatusCode == http .StatusOK {
184+ return nil
185+ }
186+ }
187+ time .Sleep (500 * time .Millisecond )
188+ }
189+ return fmt .Errorf ("not ready after %s" , timeout )
190+ }
0 commit comments