@@ -49,11 +49,17 @@ import (
4949
5050 "github.com/elastic/apm-server/systemtest/apmservertest"
5151 "github.com/elastic/apm-server/systemtest/estest"
52+ << << << < HEAD
5253 "github.com/elastic/go-elasticsearch/v7"
54+ == == == =
55+ "github.com/elastic/go-elasticsearch/v8"
56+ "github.com/elastic/go-elasticsearch/v8/esapi"
57+ >> >> >> > ec38207e (systemtest : wait for geoIP database availability (#7272 ))
5358)
5459
5560const (
5661 startContainersTimeout = 5 * time .Minute
62+ waitHealthyInterval = 5 * time .Second
5763)
5864
5965var (
@@ -110,6 +116,7 @@ func StartStackContainers() error {
110116 g , ctx := errgroup .WithContext (ctx )
111117 g .Go (func () error { return waitContainerHealthy (ctx , "kibana" ) })
112118 g .Go (func () error { return waitContainerHealthy (ctx , "fleet-server" ) })
119+ g .Go (func () error { return waitGeoIPDatabase (ctx ) })
113120 return g .Wait ()
114121}
115122
@@ -191,11 +198,51 @@ func waitContainerHealthy(ctx context.Context, serviceName string) error {
191198 log .Printf ("Waiting for %s container (%s) to become healthy" , serviceName , container .ID )
192199 first = false
193200 }
194- time .Sleep (5 * time . Second )
201+ time .Sleep (waitHealthyInterval )
195202 }
196203 return nil
197204}
198205
206+ // Elasticsearch downloads the geoIP database after starting up, and then refreshes it
207+ // periodically. In CI the cluster will be fresh, so we wait for the database to be
208+ // downloaded before running any tests which may depend on it being available.
209+ func waitGeoIPDatabase (ctx context.Context ) error {
210+ type geoIPDatabase struct {
211+ Name string
212+ }
213+ type nodeGeoIPStats struct {
214+ Databases []geoIPDatabase
215+ }
216+
217+ first := true
218+ for {
219+ var out struct {
220+ Nodes map [string ]nodeGeoIPStats
221+ }
222+ _ , err := Elasticsearch .Do (ctx , esapi.IngestGeoIPStatsRequest {}, & out )
223+ if err != nil {
224+ return err
225+ }
226+
227+ if n := len (out .Nodes ); n != 1 {
228+ return fmt .Errorf ("expected 1 node, got %d" , n )
229+ }
230+ for _ , nodeStats := range out .Nodes {
231+ for _ , db := range nodeStats .Databases {
232+ if db .Name == "GeoLite2-City.mmdb" {
233+ return nil
234+ }
235+ }
236+ }
237+
238+ if first {
239+ log .Printf ("Waiting for geoIP database to be downloaded" )
240+ first = false
241+ }
242+ time .Sleep (waitHealthyInterval )
243+ }
244+ }
245+
199246func stackContainerInfo (ctx context.Context , docker * client.Client , name string ) (* types.Container , error ) {
200247 containers , err := docker .ContainerList (ctx , types.ContainerListOptions {
201248 Filters : filters .NewArgs (
0 commit comments