@@ -16,9 +16,10 @@ import (
1616)
1717
1818var (
19- host string
20- port string
21- client * http.Client
19+ host string
20+ port string
21+ client * http.Client
22+ verbose bool
2223)
2324
2425func init () {
@@ -32,8 +33,11 @@ func init() {
3233 port = "9200"
3334 }
3435
36+ // Enable verbose logging for debugging (especially in CI)
37+ verbose = os .Getenv ("ES_CLI_VERBOSE" ) == "1" || os .Getenv ("ES_CLI_VERBOSE" ) == "true"
38+
3539 client = & http.Client {
36- Timeout : 30 * time .Second ,
40+ Timeout : 60 * time .Second ,
3741 }
3842}
3943
@@ -236,6 +240,14 @@ func executeCommand(command string) {
236240 return
237241 }
238242
243+ // Wait for index shards to be ready after PUT (index creation)
244+ if method == "PUT" && strings .HasPrefix (path , "/" ) && ! strings .Contains (path , "/_" ) {
245+ indexName := strings .Split (strings .TrimPrefix (path , "/" ), "/" )[0 ]
246+ if indexName != "" {
247+ waitForIndexReady (indexName )
248+ }
249+ }
250+
239251 // Pretty print JSON response
240252 var prettyJSON bytes.Buffer
241253 if err := json .Indent (& prettyJSON , []byte (resp ), "" , " " ); err != nil {
@@ -247,15 +259,65 @@ func executeCommand(command string) {
247259 fmt .Printf ("\n Time: %v\n " , time .Since (start ))
248260}
249261
262+ func waitForIndexReady (indexName string ) {
263+ // Wait for index shards to be ready (yellow or green status)
264+ // Use a longer timeout for CI environments and poll for readiness
265+ maxRetries := 60 // 60 seconds total
266+
267+ if verbose {
268+ fmt .Printf ("[VERBOSE] Waiting for index '%s' to be ready (max %ds)...\n " , indexName , maxRetries )
269+ }
270+
271+ for i := 0 ; i < maxRetries ; i ++ {
272+ healthPath := fmt .Sprintf ("/_cluster/health/%s" , indexName )
273+ start := time .Now ()
274+ resp , err := makeRequest ("GET" , healthPath , nil )
275+ elapsed := time .Since (start )
276+
277+ if err != nil {
278+ if verbose {
279+ fmt .Printf ("[VERBOSE] Retry %d/%d: Health check failed after %v: %v\n " , i + 1 , maxRetries , elapsed , err )
280+ }
281+ time .Sleep (1 * time .Second )
282+ continue
283+ }
284+
285+ result := gjson .Parse (resp )
286+ status := result .Get ("status" ).String ()
287+ initializingShards := result .Get ("initializing_shards" ).Int ()
288+ activeShards := result .Get ("active_shards" ).Int ()
289+
290+ if verbose {
291+ fmt .Printf ("[VERBOSE] Retry %d/%d: status=%s, initializing_shards=%d, active_shards=%d (took %v)\n " ,
292+ i + 1 , maxRetries , status , initializingShards , activeShards , elapsed )
293+ }
294+
295+ if (status == "green" || status == "yellow" ) && initializingShards == 0 {
296+ if verbose {
297+ fmt .Printf ("[VERBOSE] Index '%s' ready after %d attempts (%.2fs total)\n " , indexName , i + 1 , float64 (i + 1 ))
298+ }
299+ return // Index is ready
300+ }
301+
302+ time .Sleep (1 * time .Second )
303+ }
304+
305+ // Log warning but don't fail - the index might still become available
306+ fmt .Printf ("Warning: Index %s not ready after %d seconds\n " , indexName , maxRetries )
307+ }
308+
250309func makeRequest (method , path string , body []byte ) (string , error ) {
251310 url := fmt .Sprintf ("http://%s:%s%s" , host , port , path )
311+ start := time .Now ()
252312
253313 var req * http.Request
254314 var err error
255315
256316 if body != nil {
257317 req , err = http .NewRequest (method , url , bytes .NewBuffer (body ))
258- req .Header .Set ("Content-Type" , "application/json" )
318+ if err == nil {
319+ req .Header .Set ("Content-Type" , "application/json" )
320+ }
259321 } else {
260322 req , err = http .NewRequest (method , url , nil )
261323 }
@@ -264,17 +326,41 @@ func makeRequest(method, path string, body []byte) (string, error) {
264326 return "" , err
265327 }
266328
329+ if verbose {
330+ bodyPreview := ""
331+ if body != nil && len (body ) > 0 {
332+ if len (body ) > 100 {
333+ bodyPreview = fmt .Sprintf (" (body: %d bytes)" , len (body ))
334+ } else {
335+ bodyPreview = fmt .Sprintf (" (body: %s)" , string (body ))
336+ }
337+ }
338+ fmt .Printf ("[VERBOSE] Request: %s %s%s\n " , method , path , bodyPreview )
339+ }
340+
267341 resp , err := client .Do (req )
342+ elapsed := time .Since (start )
343+
268344 if err != nil {
345+ if verbose {
346+ fmt .Printf ("[VERBOSE] Request failed after %v: %v\n " , elapsed , err )
347+ }
269348 return "" , err
270349 }
271350 defer resp .Body .Close ()
272351
273352 respBody , err := io .ReadAll (resp .Body )
274353 if err != nil {
354+ if verbose {
355+ fmt .Printf ("[VERBOSE] Failed to read response body after %v: %v\n " , elapsed , err )
356+ }
275357 return "" , err
276358 }
277359
360+ if verbose {
361+ fmt .Printf ("[VERBOSE] Response: HTTP %d (took %v, %d bytes)\n " , resp .StatusCode , elapsed , len (respBody ))
362+ }
363+
278364 if resp .StatusCode >= 400 {
279365 return string (respBody ), fmt .Errorf ("HTTP %d: %s" , resp .StatusCode , resp .Status )
280366 }
0 commit comments