-
Notifications
You must be signed in to change notification settings - Fork 5k
Add helper to get hosts on Go Metricbeat integration tests #13055
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0cfe2c6
61ef8af
a7571c5
cbd580b
6a3972a
9039a75
e20f5df
256d94c
c5e3f8b
f32f91a
c78cdc5
91600f1
c258f73
3947210
ba8680f
a07dbc1
c9e9d0b
576c0e6
1da2b39
4597193
f40f1a6
8a80ccf
f4e4f1a
e1f60ac
c774eb3
fc04ade
b0b7468
2b6905b
f30d1ac
5147b0a
4f8b471
9dcb2f9
0e080c4
e8941df
b523145
aa1b613
71eb5b8
591057a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,74 +19,152 @@ package compose | |
|
|
||
| import ( | ||
| "errors" | ||
| "fmt" | ||
| "os" | ||
| "path/filepath" | ||
| "strconv" | ||
| "strings" | ||
| "testing" | ||
| "time" | ||
| ) | ||
|
|
||
| // HostInfo exposes information about started scenario | ||
| type HostInfo interface { | ||
| // Host returns an address as host:port that can be used to connect to | ||
| // a running service. | ||
| Host() string | ||
|
|
||
| // HostForPort returns an address as host:port that can be used to | ||
| // connect to a running service that has multiple exposed ports. The | ||
| // address returned is the one that can be used to connect to the | ||
| // indicated exposed port. | ||
| HostForPort(port int) string | ||
| } | ||
|
|
||
| // EnsureUp starts all the requested services (must be defined in docker-compose.yml) | ||
| // with a default timeout of 300 seconds | ||
| func EnsureUp(t *testing.T, services ...string) { | ||
| EnsureUpWithTimeout(t, 60, services...) | ||
| } | ||
| func EnsureUp(t testing.TB, service string, options ...UpOption) HostInfo { | ||
| t.Helper() | ||
|
|
||
| // EnsureUpWithTimeout starts all the requested services (must be defined in docker-compose.yml) | ||
| // Wait for `timeout` seconds for health | ||
| func EnsureUpWithTimeout(t *testing.T, timeout int, services ...string) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what’s the reason to accept only one service? not saying it’s a bad idea, just want to know the reasoning
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are two main reasons:
If wouldn't be hard to implement it though, by returning a struct with all the services info and adding a method like
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That sounds good to me, thanks for the explanation! |
||
| // The NO_COMPOSE env variables makes it possible to skip the starting of the environment. | ||
| // This is useful if the service is already running locally. | ||
| if noCompose, err := strconv.ParseBool(os.Getenv("NO_COMPOSE")); err == nil && noCompose { | ||
| return | ||
| if hostInfo := HostInfoFromEnv(t, service); hostInfo != nil { | ||
| return hostInfo | ||
| } | ||
|
|
||
| compose, err := getComposeProject() | ||
| compose, err := getComposeProject(os.Getenv("DOCKER_COMPOSE_PROJECT_NAME")) | ||
| if err != nil { | ||
| t.Fatal(err) | ||
| } | ||
| defer compose.Close() | ||
|
|
||
| // Kill no longer used containers | ||
| err = compose.KillOld(services) | ||
| err = compose.KillOld([]string{service}) | ||
| if err != nil { | ||
| t.Fatal(err) | ||
| } | ||
|
|
||
| for _, service := range services { | ||
| err = compose.Start(service) | ||
| if err != nil { | ||
| t.Fatal("failed to start service", service, err) | ||
| } | ||
| upOptions := UpOptions{ | ||
| Timeout: 60 * time.Second, | ||
| Create: CreateOptions{ | ||
| Build: true, | ||
| ForceRecreate: true, | ||
| }, | ||
| } | ||
| for _, option := range options { | ||
| option(&upOptions) | ||
| } | ||
|
|
||
| // Start container | ||
| err = compose.Start(service, upOptions) | ||
| if err != nil { | ||
| t.Fatal("failed to start service", service, err) | ||
| } | ||
|
|
||
| // Wait for health | ||
| err = compose.Wait(timeout, services...) | ||
| err = compose.Wait(upOptions.Timeout, service) | ||
| if err != nil { | ||
| t.Fatal(err) | ||
| } | ||
|
|
||
| // Get host information | ||
| host, err := compose.HostInformation(service) | ||
| if err != nil { | ||
| t.Fatalf("getting host for %s", service) | ||
| } | ||
|
|
||
| return host | ||
| } | ||
|
|
||
| func getComposeProject() (*Project, error) { | ||
| // EnsureUpWithTimeout starts all the requested services (must be defined in docker-compose.yml) | ||
| // Wait for `timeout` seconds for health | ||
| func EnsureUpWithTimeout(t testing.TB, timeout int, service string) HostInfo { | ||
| return EnsureUp(t, service, UpWithTimeout(time.Duration(timeout)*time.Second)) | ||
| } | ||
|
|
||
| // HostInfoFromEnv gets the host information to use for the test from environment variables. | ||
| func HostInfoFromEnv(t testing.TB, service string) HostInfo { | ||
| // If an environment variable with the form <SERVICE>_HOST is used, its value | ||
| // is used as host instead of starting a new service. | ||
| envVar := fmt.Sprintf("%s_HOST", strings.ToUpper(service)) | ||
| host := os.Getenv(envVar) | ||
| if host != "" { | ||
| return &staticHostInfo{host: host} | ||
| } | ||
|
|
||
| // The NO_COMPOSE env variables makes it possible to skip the starting of the environment. | ||
| // This is useful if the service is already running locally. | ||
| // Kept for historical reasons, now it only complains if the host environment | ||
| // variable is not set. | ||
| noCompose, err := strconv.ParseBool(os.Getenv("NO_COMPOSE")) | ||
| if err == nil && noCompose { | ||
| t.Fatalf("%s environment variable must be set as the host:port where %s is running", envVar, service) | ||
| } | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| type staticHostInfo struct { | ||
| host string | ||
| } | ||
|
|
||
| func (i *staticHostInfo) Host() string { | ||
| return i.host | ||
| } | ||
|
|
||
| func (i *staticHostInfo) HostForPort(int) string { | ||
| return i.host | ||
| } | ||
|
|
||
| func findComposePath() (string, error) { | ||
| // find docker-compose | ||
| path, err := os.Getwd() | ||
| if err != nil { | ||
| return nil, err | ||
| return "", err | ||
| } | ||
| for { | ||
| if path == "/" { | ||
| return nil, errors.New("docker-compose.yml not found") | ||
| break | ||
| } | ||
|
|
||
| if _, err = os.Stat(filepath.Join(path, "docker-compose.yml")); err != nil { | ||
| path = filepath.Dir(path) | ||
| } else { | ||
| break | ||
| composePath := filepath.Join(path, "docker-compose.yml") | ||
| if _, err = os.Stat(composePath); err == nil { | ||
| return composePath, nil | ||
| } | ||
| path = filepath.Dir(path) | ||
| } | ||
|
|
||
| return "", errors.New("docker-compose.yml not found") | ||
| } | ||
|
|
||
| func getComposeProject(name string) (*Project, error) { | ||
| path, err := findComposePath() | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return NewProject( | ||
| os.Getenv("DOCKER_COMPOSE_PROJECT_NAME"), | ||
| name, | ||
| []string{ | ||
| filepath.Join(path, "docker-compose.yml"), | ||
| path, | ||
| }, | ||
| ) | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.