Skip to content
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

[WIP/Ideas] Config matrices for integration tests #7957

Closed
wants to merge 106 commits into from
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
f67d8d7
Initial implementation of compose test runner
jsoriano Aug 13, 2018
39cb492
Parallel
jsoriano Aug 13, 2018
1f12a3e
More parallel
jsoriano Aug 13, 2018
56729d7
--no-ansi for compose
jsoriano Aug 14, 2018
ce4ab51
Randomize project name
jsoriano Aug 14, 2018
c2b8060
Seed random generator for compose project names
jsoriano Aug 14, 2018
166709d
Migrate info metricset
jsoriano Aug 14, 2018
0f1a8d6
Run test suites
jsoriano Aug 14, 2018
89f5f0e
Allow to override compose runner host and options
jsoriano Aug 15, 2018
57e11ea
Typo
jsoriano Aug 15, 2018
d7fe343
Use more explicit healthcheck for redis
jsoriano Aug 15, 2018
d71d210
Keep a redis service in the main docker-compose file
jsoriano Aug 17, 2018
938ba32
Redis test use compose provided hosts
jsoriano Aug 21, 2018
4301a8d
Run beat container in host network mode
jsoriano Aug 21, 2018
a572279
Run redis python tests with two versions
jsoriano Aug 21, 2018
180e31f
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Aug 21, 2018
8dd0a98
Add compose runner for kafka
jsoriano Aug 21, 2018
38cc081
Use docker compose 2.1 version
jsoriano Aug 21, 2018
b3981f7
Use kafka runner in consumergroup metricset
jsoriano Aug 21, 2018
b6735ea
Retry on docker compose up to avoid failures by system limits
jsoriano Aug 23, 2018
17c3f2a
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Aug 23, 2018
f9f0cd1
Use compose runner for aerospike
jsoriano Aug 23, 2018
a7382e6
Inject a runner controller instead of just the host
jsoriano Aug 23, 2018
760cdc3
Remove local images on down
jsoriano Aug 23, 2018
9b9f5be
Add more versions to aerospike
jsoriano Aug 23, 2018
f45c67e
Use compose runner for apache module
jsoriano Aug 23, 2018
88f3ff8
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Aug 23, 2018
821f71a
Revert "Remove local images on down"
jsoriano Aug 23, 2018
d1321cc
Revert "Revert "Remove local images on down""
jsoriano Aug 24, 2018
12f1e20
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Aug 31, 2018
f2896de
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Sep 6, 2018
13252a6
Using public ports as host addresses
jsoriano Sep 6, 2018
0117461
Inject context information into the compose containers
jsoriano Sep 7, 2018
2ca7e84
Keep environment when calling docker compose
jsoriano Sep 7, 2018
113f947
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Sep 11, 2018
2246ccb
pep8
jsoriano Sep 11, 2018
5e4335c
Add type to simplify config of test runners
jsoriano Sep 11, 2018
9a21006
Run dropwizard tests with testrunner
jsoriano Sep 11, 2018
edc7982
Run ES tests with testrunner
jsoriano Sep 11, 2018
a322c5f
Run envoyproxy tests with testrunner
jsoriano Sep 11, 2018
476530a
Run etcd tests with testrunner
jsoriano Sep 11, 2018
46bc089
Run jolokia tests with testrunner
jsoriano Sep 11, 2018
4a036b7
Run http tests with testrunner
jsoriano Sep 11, 2018
084e28e
Run kibana tests with testrunner
jsoriano Sep 11, 2018
9d93da7
Run logstash tests with testrunner
jsoriano Sep 11, 2018
9368483
Skip tests using EnsureUp by now
jsoriano Sep 11, 2018
26e33a6
Fix environment setting
jsoriano Sep 11, 2018
fb97295
Test elasticsearch on multiple versions
jsoriano Sep 11, 2018
ba2cac4
Expose options to tests
jsoriano Sep 11, 2018
44a8772
Fix kafka python tests
jsoriano Sep 12, 2018
6881d7b
Use alpine jre image for kafka
jsoriano Sep 12, 2018
eb3c9fe
Actually test kafka with multiple versions, and reuse images
jsoriano Sep 12, 2018
22367be
Fix golang python test
jsoriano Sep 12, 2018
b3f09e0
Fix kibana python test
jsoriano Sep 12, 2018
3fcd7b8
Fix test_base python test
jsoriano Sep 12, 2018
fcfb663
Fix docker python test
jsoriano Sep 12, 2018
f0f9954
Generate data in kafka tests before starting consumer
jsoriano Sep 13, 2018
6c0f666
Reduce number of kafka partitions in tests
jsoriano Sep 13, 2018
c14c93e
Don't prebuild docker images
jsoriano Sep 13, 2018
39d3b1b
Fix uwsgi python test
jsoriano Sep 12, 2018
082801d
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Oct 28, 2018
ab3a368
Run zookeeper tests with testrunner
jsoriano Oct 28, 2018
e1d587c
Run memcached tests with testrunner
jsoriano Oct 28, 2018
267a561
Run uwsgi tests with testrunner
jsoriano Oct 28, 2018
263ec8a
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Nov 9, 2018
513976b
Run traefik tests with testrunner
jsoriano Nov 9, 2018
8d3ed55
Run rabbitmq tests with testrunner
jsoriano Nov 10, 2018
23d4e7f
Run postgresql tests with testrunner
jsoriano Nov 10, 2018
a337d77
Set a default name for compose test scenarios without variables
jsoriano Nov 11, 2018
e4b209f
Run prometheus tests with testrunner
jsoriano Nov 11, 2018
45e1950
Run mysql tests with testrunner
jsoriano Nov 12, 2018
972e304
Run php_fpm tests with testrunner
jsoriano Nov 12, 2018
ad8d2bc
Run nginx tests with testrunner
jsoriano Nov 12, 2018
47fe928
Run mongodb tests with testrunner
jsoriano Nov 12, 2018
1973703
Remove unused EnsureUp
jsoriano Nov 12, 2018
7a4a29d
Fix default description
jsoriano Nov 12, 2018
78a9fe1
Allow to use runner ctl as T
jsoriano Nov 12, 2018
605e642
Get compose hosts from docker in python tests
jsoriano Nov 12, 2018
3fc2715
Fix traefik test
jsoriano Nov 14, 2018
fd4fcd6
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Nov 14, 2018
58c4e28
Add also implementation for private port to python
jsoriano Nov 15, 2018
8c890bf
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Nov 18, 2018
58981e5
Better error message if no port is configured
jsoriano Nov 20, 2018
a0d8c3e
Fix etcd system tests
jsoriano Nov 20, 2018
a7191c0
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Nov 21, 2018
95696e5
Properly wrap testing.T into runner control
jsoriano Nov 22, 2018
4e6904a
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Nov 22, 2018
6ba4e9d
Move compose test functions to top-level
jsoriano Nov 23, 2018
7a0c524
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Nov 23, 2018
494aa29
Fix tests after refactor
jsoriano Nov 23, 2018
345e4cc
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Nov 27, 2018
1f0bb6f
Remove leftover comment
jsoriano Nov 27, 2018
77e24a7
Try to make hound CI happy
jsoriano Nov 27, 2018
d80c4d4
Remove commented out line
jsoriano Nov 27, 2018
fc39b36
Add tests for scenarios
jsoriano Nov 27, 2018
27f457d
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Jan 18, 2019
0de565e
Fix nats tests
jsoriano Jan 19, 2019
a200df2
Add ES versions
jsoriano Jan 19, 2019
76a402c
Fix mssql tests
jsoriano Jan 19, 2019
fae8cda
Update versions of the stack
jsoriano Jan 20, 2019
ffe2062
Fix redis key test
jsoriano Jan 20, 2019
dfd3e0d
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Mar 5, 2019
86cc04b
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Mar 6, 2019
90a9e0f
Merge remote-tracking branch 'origin/master' into compose-test-runner
jsoriano Mar 6, 2019
64dfd65
Move couchbase DSN helper to mtest
jsoriano Mar 6, 2019
2c9cd97
Fix mysql tests
jsoriano Mar 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions libbeat/tests/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ func EnsureUpWithTimeout(t *testing.T, timeout int, services ...string) {
return
}

compose, err := getComposeProject()
name := os.Getenv("DOCKER_COMPOSE_PROJECT_NAME")
compose, err := getComposeProject(name)
if err != nil {
t.Fatal(err)
}
Expand All @@ -65,28 +66,37 @@ func EnsureUpWithTimeout(t *testing.T, timeout int, services ...string) {
}
}

func getComposeProject() (*Project, error) {
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,
},
)
}
46 changes: 34 additions & 12 deletions libbeat/tests/compose/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,13 @@ const (
// Driver is the interface of docker compose implementations
type Driver interface {
Up(ctx context.Context, opts UpOptions, service string) error
Down(ctx context.Context) error
Kill(ctx context.Context, signal string, service string) error
Ps(ctx context.Context, filter ...string) ([]ContainerStatus, error)
// Containers(ctx context.Context, projectFilter Filter, filter ...string) ([]string, error)

SetParameters(map[string]string)

LockFile() string
}

Expand All @@ -69,6 +72,7 @@ type ContainerStatus interface {
Healthy() bool
Running() bool
Old() bool
Host() string
}

// Project is a docker-compose project
Expand All @@ -94,18 +98,6 @@ func NewProject(name string, files []string) (*Project, error) {

// Start the container, unless it's running already
func (c *Project) Start(service string) error {
servicesStatus, err := c.getServices(service)
if err != nil {
return err
}

if servicesStatus[service] != nil {
if servicesStatus[service].Running {
// Someone is running it
return nil
}
}

c.Lock()
defer c.Unlock()

Expand Down Expand Up @@ -149,6 +141,25 @@ func (c *Project) Wait(seconds int, services ...string) error {
return nil
}

// Host gets the host and port of a service
func (c *Project) Host(service string) (string, error) {
servicesStatus, err := c.getServices(service)
if err != nil {
return "", err
}

if len(servicesStatus) == 0 {
return "", errors.New("no container running for service")
}

status, ok := servicesStatus[service]
if !ok || status.Host == "" {
return "", errors.New("unknown host:port for service")
}

return status.Host, nil
}

// Kill a container
func (c *Project) Kill(service string) error {
c.Lock()
Expand Down Expand Up @@ -190,6 +201,14 @@ func (c *Project) KillOld(except []string) error {
return nil
}

// Down removes all resources of a project
func (c *Project) Down() error {
c.Lock()
defer c.Unlock()

return c.Driver.Down(context.Background())
}

// Lock acquires the lock (300s) timeout
// Normally it should only be seconds that the lock is used, but in some cases it can take longer.
func (c *Project) Lock() {
Expand Down Expand Up @@ -226,6 +245,8 @@ type serviceInfo struct {
Running bool
Healthy bool

Host string

// Has been up for too long?:
Old bool
}
Expand Down Expand Up @@ -259,6 +280,7 @@ func (c *Project) getServices(filter ...string) (map[string]*serviceInfo, error)
if service.Healthy {
service.Old = c.Old()
}
service.Host = c.Host()
result[name] = service
}

Expand Down
119 changes: 119 additions & 0 deletions libbeat/tests/compose/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package compose

import (
"fmt"
"math/rand"
"os"
"sort"
"strings"
"testing"
"time"

"github.com/pkg/errors"
)

func init() {
rand.Seed(time.Now().UnixNano())
}

type TestRunner struct {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported type TestRunner should have comment or be unexported

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported type TestRunner should have comment or be unexported

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported type TestRunner should have comment or be unexported

Service string
Options map[string][]string
Parallel bool
Timeout int
}

type Suite map[string]func(t *testing.T, host string)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported type Suite should have comment or be unexported


func (r *TestRunner) scenarios() []map[string]string {
n := 1
for _, values := range r.Options {
n *= len(values)
}

scenarios := make([]map[string]string, n)
for variable, values := range r.Options {
v := 0
for i, s := range scenarios {
if s == nil {
s = make(map[string]string)
scenarios[i] = s
}
s[variable] = values[v]
v = (v + 1) % len(values)
}
}

return scenarios
}

func (r *TestRunner) Run(t *testing.T, tests Suite) {
jsoriano marked this conversation as resolved.
Show resolved Hide resolved
jsoriano marked this conversation as resolved.
Show resolved Hide resolved
jsoriano marked this conversation as resolved.
Show resolved Hide resolved
timeout := r.Timeout
if timeout == 0 {
timeout = 300
}

for _, s := range r.scenarios() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to still have something like NO_COMPOSE=1 that can be set if the environment is already running on the local machine so it will not start up all docker containers. Perhaps that still exists ...

Copy link
Member Author

@jsoriano jsoriano Aug 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have just added something like this, look at 89f5f0e

I prefer to do it as a host override instead of only a feature disable for two reasons:

  • Depending on how you are running the environment you want to test with you are going to need to override the host in any case
  • "Running environment" is going to be trickier now, as each service can be running with multiple versions and configurations

var vars []string
for k, v := range s {
os.Setenv(k, v)
vars = append(vars, fmt.Sprintf("%s=%s", k, v))
}
sort.Strings(vars)
desc := strings.Join(vars, ",")

seq := make([]byte, 16)
rand.Read(seq)
name := fmt.Sprintf("%s_%x", r.Service, seq)

project, err := getComposeProject(name)
if err != nil {
t.Fatal(err)
}
project.SetParameters(s)

t.Run(desc, func(t *testing.T) {
if r.Parallel {
t.Parallel()
}

err := project.Start(r.Service)
if err != nil {
t.Fatal(err)
}
defer project.Down()

err = project.Wait(timeout, r.Service)
if err != nil {
t.Fatal(errors.Wrapf(err, "waiting for %s/%s", r.Service, desc))
}

host, err := project.Host(r.Service)
if err != nil {
t.Fatal(errors.Wrapf(err, "getting host for %s/%s", r.Service, desc))
}

for name, test := range tests {
t.Run(name, func(t *testing.T) { test(t, host) })
}
})

}
}
42 changes: 40 additions & 2 deletions libbeat/tests/compose/wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ package compose
import (
"context"
"fmt"
"net"
"os"
"os/exec"
"strconv"
"strings"

"github.com/pkg/errors"
Expand All @@ -39,6 +41,8 @@ const (
type wrapperDriver struct {
Name string
Files []string

Environment []string
}

type wrapperContainer struct {
Expand All @@ -61,13 +65,32 @@ func (c *wrapperContainer) Old() bool {
return strings.Contains(c.info.Status, "minute")
}

func (c *wrapperContainer) Host() string {
// TODO: Support multiple networks/ports
var ip string
for _, net := range c.info.NetworkSettings.Networks {
if len(net.IPAddress) > 0 {
ip = net.IPAddress
break
}
}
if len(ip) == 0 {
return ""
}

for _, port := range c.info.Ports {
return net.JoinHostPort(ip, strconv.Itoa(int(port.PrivatePort)))
}
return ""
}

func (d *wrapperDriver) LockFile() string {
return d.Files[0] + ".lock"
return d.Files[0] + "." + d.Name + ".lock"
}

func (d *wrapperDriver) cmd(ctx context.Context, command string, arg ...string) *exec.Cmd {
var args []string
args = append(args, "--project-name", d.Name)
args = append(args, "--no-ansi", "--project-name", d.Name)
for _, f := range d.Files {
args = append(args, "--file", f)
}
Expand All @@ -76,9 +99,20 @@ func (d *wrapperDriver) cmd(ctx context.Context, command string, arg ...string)
cmd := exec.CommandContext(ctx, "docker-compose", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if len(d.Environment) > 0 {
cmd.Env = d.Environment
}
return cmd
}

func (d *wrapperDriver) SetParameters(params map[string]string) {
var env []string
for k, v := range params {
env = append(env, fmt.Sprintf("%s=%s", k, v))
}
d.Environment = env
}

func (d *wrapperDriver) Up(ctx context.Context, opts UpOptions, service string) error {
var args []string

Expand All @@ -99,6 +133,10 @@ func (d *wrapperDriver) Up(ctx context.Context, opts UpOptions, service string)
return d.cmd(ctx, "up", args...).Run()
}

func (d *wrapperDriver) Down(ctx context.Context) error {
return d.cmd(ctx, "down", "-v").Run()
}

func (d *wrapperDriver) Kill(ctx context.Context, signal string, service string) error {
var args []string

Expand Down
6 changes: 2 additions & 4 deletions metricbeat/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
version: '2'
version: "2"

services:
beat:
build: ${PWD}/.
Expand Down Expand Up @@ -156,9 +157,6 @@ services:
rabbitmq:
build: ./module/rabbitmq/_meta

redis:
build: ./module/redis/_meta

traefik:
build: ./module/traefik/_meta

Expand Down
2 changes: 0 additions & 2 deletions metricbeat/module/redis/_meta/Dockerfile

This file was deleted.

11 changes: 11 additions & 0 deletions metricbeat/module/redis/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version: "2.4"

services:
redis:
image: redis:${REDIS_VERSION:-4.0.11}-${IMAGE_OS:-alpine}
healthcheck:
test:
- "CMD-SHELL"
- "nc -z localhost 6379"
interval: 1s
retries: 90
Loading