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

[Not for merge] Testing CI fixes #38718

Closed
wants to merge 13 commits into from
Closed
11 changes: 10 additions & 1 deletion dev-tools/mage/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"errors"
"fmt"
"io"
"io/ioutil"

Check failure on line 35 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

SA1019: "io/ioutil" has been deprecated since Go 1.19: As of Go 1.16, the same functionality is now provided by package [io] or package [os], and those implementations should be preferred in new code. See the specific function documentation for details. (staticcheck)
"log"
"net/http"
"os"
Expand Down Expand Up @@ -219,10 +219,19 @@
// HaveDockerCompose returns an error if docker-compose is not found on the
// PATH.
func HaveDockerCompose() error {
_, err := exec.LookPath("docker-compose")

path, err := exec.LookPath("docker")
if err != nil {
return fmt.Errorf("docker is not available")
} else {
fmt.Printf("hi fae, docker is at %v\n", path)
}

path, err = exec.LookPath("docker-compose")
if err != nil {
return fmt.Errorf("docker-compose is not available")
}
fmt.Printf("hi fae, docker compose is %v\n", path)
return nil
}

Expand Down Expand Up @@ -283,7 +292,7 @@
func DownloadFile(url, destinationDir string) (string, error) {
log.Println("Downloading", url)

resp, err := http.Get(url)

Check failure on line 295 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

G107: Potential HTTP request made with variable url (gosec)
if err != nil {
return "", fmt.Errorf("http get failed: %w", err)
}
Expand Down Expand Up @@ -338,7 +347,7 @@
}
defer innerFile.Close()

path := filepath.Join(destinationDir, f.Name)

Check failure on line 350 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

G305: File traversal when extracting zip/tar archive (gosec)
if !strings.HasPrefix(path, destinationDir) {
return fmt.Errorf("illegal file path in zip: %v", f.Name)
}
Expand All @@ -357,7 +366,7 @@
}
defer out.Close()

if _, err = io.Copy(out, innerFile); err != nil {

Check failure on line 369 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

G110: Potential DoS vulnerability via decompression bomb (gosec)
return err
}

Expand Down Expand Up @@ -390,7 +399,7 @@
tw := tar.NewWriter(zr)

// walk through every file in the folder
filepath.Walk(src, func(file string, fi os.FileInfo, errFn error) error {

Check failure on line 402 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

Error return value of `filepath.Walk` is not checked (errcheck)
if errFn != nil {
return fmt.Errorf("error traversing the file system: %w", errFn)
}
Expand Down Expand Up @@ -477,13 +486,13 @@
for {
header, err := tarReader.Next()
if err != nil {
if err == io.EOF {

Check failure on line 489 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

comparing with == will fail on wrapped errors. Use errors.Is to check for a specific error (errorlint)
break
}
return err
}

path := filepath.Join(destinationDir, header.Name)

Check failure on line 495 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

G305: File traversal when extracting zip/tar archive (gosec)
if !strings.HasPrefix(path, destinationDir) {
return fmt.Errorf("illegal file path in tar: %v", header.Name)
}
Expand All @@ -499,7 +508,7 @@
return err
}

if _, err = io.Copy(writer, tarReader); err != nil {

Check failure on line 511 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

G110: Potential DoS vulnerability via decompression bomb (gosec)
return err
}

Expand Down Expand Up @@ -575,7 +584,7 @@
// based on GOMAXPROCS. The provided ctx is passed to the functions (if they
// accept it as a param).
func ParallelCtx(ctx context.Context, fns ...interface{}) {
var fnWrappers []func(context.Context) error

Check failure on line 587 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

Consider pre-allocating `fnWrappers` (prealloc)
for _, f := range fns {
fnWrapper := funcTypeWrap(f)
if fnWrapper == nil {
Expand Down Expand Up @@ -800,7 +809,7 @@

var files []string
for _, s := range sources {
filepath.Walk(s, func(path string, info os.FileInfo, err error) error {

Check failure on line 812 in dev-tools/mage/common.go

View workflow job for this annotation

GitHub Actions / lint (windows)

Error return value of `filepath.Walk` is not checked (errcheck)
if err != nil {
if os.IsNotExist(err) {
return nil
Expand Down
3 changes: 3 additions & 0 deletions dev-tools/mage/integtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ func NewIntegrationRunners(path string, passInEnv map[string]string) (Integratio

// NewDockerIntegrationRunner returns an integration runner configured only for docker.
func NewDockerIntegrationRunner(passThroughEnvVars ...string) (*IntegrationRunner, error) {
fmt.Printf("hi fae, NewDockerIntegrationRunner\n")
cwd, err := os.Getwd()
if err != nil {
return nil, err
Expand All @@ -223,9 +224,11 @@ func NewDockerIntegrationRunner(passThroughEnvVars ...string) (*IntegrationRunne
}

func initRunner(tester IntegrationTester, dir string, passInEnv map[string]string, passThroughEnvVars ...string) (*IntegrationRunner, error) {
fmt.Printf("hi fae, initRunner\n")
var runnerSteps IntegrationTestSteps
requirements := tester.StepRequirements()
if requirements != nil {
fmt.Printf("hi fae, requirements: %v\n", requirements.Name())
runnerSteps = append(runnerSteps, requirements...)
}

Expand Down
4 changes: 4 additions & 0 deletions dev-tools/mage/integtest_docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,15 @@ func (d *DockerIntegrationTester) Use(dir string) (bool, error) {

// HasRequirements ensures that the required docker and docker-compose are installed.
func (d *DockerIntegrationTester) HasRequirements() error {
fmt.Printf("hi fae, in DockerIntegrationTester.HasRequirements\n")
if err := HaveDocker(); err != nil {
return err
}
if err := HaveDockerCompose(); err != nil {
return err
}
fmt.Printf("hi fae, everything passed\n")
//os.Exit(1)
return nil
}

Expand All @@ -88,6 +91,7 @@ func (d *DockerIntegrationTester) StepRequirements() IntegrationTestSteps {
// Test performs the tests with docker-compose. The compose file must define a "beat" container,
// containing the beats development environment. The tests are executed from within this container.
func (d *DockerIntegrationTester) Test(dir string, mageTarget string, env map[string]string) error {
fmt.Printf("hi fae, DockerIntegrationTester.Test\n")
var err error
buildContainersOnce.Do(func() { err = BuildIntegTestContainers() })
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions libbeat/tests/system/beat/beat.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,12 @@ def compose_up_with_retries(cls):
retries = 3
for i in range(retries):
try:
print("hi fae, trying compose_up")
cls.compose_up()
print("hi fae, compose_up succeeded")
return
except Exception as ex:
print("hi fae, compose_up failed")
if i + 1 >= retries:
raise ex
print(f"Compose up failed, retrying: {ex}")
Expand Down
93 changes: 53 additions & 40 deletions libbeat/tests/system/beat/compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,39 +49,45 @@ def compose_up(cls):
return

def print_logs(container):
print("---- " + container.name_without_project)
print("---- " + container.name)
print(container.logs())
print("----")

def is_healthy(container):
return container.inspect()['State']['Health']['Status'] == 'healthy'
return container.state.health.status == 'healthy' #container.inspect()['State']['Health']['Status'] == 'healthy'

project = cls.compose_project()

with disabled_logger('compose.service'):
project.pull(
ignore_pull_failures=True,
service_names=cls.COMPOSE_SERVICES)
services=cls.COMPOSE_SERVICES)

# project.up(
# strategy=ConvergenceStrategy.always,
# service_names=cls.COMPOSE_SERVICES,
# timeout=30)
project.up(
strategy=ConvergenceStrategy.always,
service_names=cls.COMPOSE_SERVICES,
timeout=30)
services=cls.COMPOSE_SERVICES,
recreate=True,
detach=True,
)

# Wait for them to be healthy
start = time.time()
while True:
containers = project.containers(
service_names=cls.COMPOSE_SERVICES,
stopped=True)
# containers = project.containers(
# service_names=cls.COMPOSE_SERVICES,
# stopped=True)
containers = project.ps(services=cls.COMPOSE_SERVICES, all=True)

healthy = True
for container in containers:
if not container.is_running:
if not container.state.status == 'running':
print_logs(container)
raise Exception(
"Container %s unexpectedly finished on startup" %
container.name_without_project)
container.name)
if not is_healthy(container):
healthy = False
break
Expand Down Expand Up @@ -114,19 +120,10 @@ def _setup_advertised_host(cls, project, service):
"""
host = cls.compose_host(service=service, port=cls.COMPOSE_ADVERTISED_PORT)

content = "SERVICE_HOST=%s" % host
info = tarfile.TarInfo(name="/run/compose_env")
info.mode = 0o100644
info.size = len(content)

data = io.BytesIO()
tar = tarfile.TarFile(fileobj=data, mode='w')
tar.addfile(info, fileobj=io.BytesIO(content.encode("utf-8")))
tar.close()

containers = project.containers(service_names=[service])
containers = project.ps(services=[service])
for container in containers:
container.client.put_archive(container=container.id, path="/", data=data.getvalue())
container.execute(["sh", "-c", "echo SERVICE_HOST=%s >/run/compose_env" % host])
container.execute(["sh", "-c", "chmod 644 /run/compose_env"])

@classmethod
def compose_down(cls):
Expand All @@ -139,36 +136,37 @@ def compose_down(cls):
if INTEGRATION_TESTS and cls.COMPOSE_SERVICES:
# Use down on per-module scenarios to release network pools too
if os.path.basename(os.path.dirname(cls.find_compose_path())) == "module":
cls.compose_project().down(remove_image_type=None, include_volumes=True)
cls.compose_project().down(volumes=True)
else:
cls.compose_project().kill(service_names=cls.COMPOSE_SERVICES)
cls.compose_project().kill(services=cls.COMPOSE_SERVICES)

@classmethod
def get_hosts(cls):
return [cls.compose_host()]

@classmethod
def _private_host(cls, info, port):
def _private_host(cls, networks, port):
"""
Return the address of the container, it should be reachable from the
host if docker is being run natively. To be used when the tests are
run from another container in the same network. It also works when
running from the host network if the docker daemon runs natively.
"""
networks = list(info['NetworkSettings']['Networks'].values())
#networks = list(info['NetworkSettings']['Networks'].values())
networks = list(networks.values())
port = port.split("/")[0]
for network in networks:
ip = network['IPAddress']
ip = network.ip_address
if ip:
return "%s:%s" % (ip, port)

@classmethod
def _exposed_host(cls, info, port):
def _exposed_host(cls, network_settings, port):
"""
Return the exposed address in the host, can be used when the test is
run from the host network. Recommended when using docker machines.
"""
hostPort = info['NetworkSettings']['Ports'][port][0]['HostPort']
hostPort = network_settings.ports[port][0]['HostPort']
return "localhost:%s" % hostPort

@classmethod
Expand All @@ -183,19 +181,20 @@ def compose_host(cls, service=None, port=None):
if host_env:
return host_env

container = cls.compose_project().containers(service_names=[service])[0]
info = container.inspect()
portsConfig = info['HostConfig']['PortBindings']
container = cls.compose_project().ps(services=[service])[0]
# info = container.inspect()
portsConfig = container.host_config.port_bindings #info['HostConfig']['PortBindings']
if len(portsConfig) == 0:
raise Exception("No exposed ports for service %s" % service)
if port is None:
port = list(portsConfig.keys())[0]

# We can use _exposed_host for all platforms when we can use host network
# in the metricbeat container
# networks = list(info['NetworkSettings']['Networks'].values())
if sys.platform.startswith('linux'):
return cls._private_host(info, port)
return cls._exposed_host(info, port)
return cls._private_host(container.network_settings.networks, port)
return cls._exposed_host(container.network_settings, port)

@classmethod
def compose_project_name(cls):
Expand All @@ -210,9 +209,23 @@ def positivehash(x):
def compose_project(cls):
env = Environment(os.environ.copy())
env.update(cls.COMPOSE_ENV)
return get_project(cls.find_compose_path(),
project_name=cls.compose_project_name(),
environment=env)

compose_files = [os.path.join(cls.find_compose_path(), "docker-compose.yml")]

print("hi fae, in compose_project")
import shutil
print("hi fae, docker: %s" % shutil.which("docker"))
print("hi fae, docker-compose: %s" % shutil.which("docker-compose"))
print("hi fae, isfile(/bin/docker):", os.path.isfile("/bin/docker"))

from python_on_whales import DockerClient
docker = DockerClient(
compose_project_name=cls.compose_project_name().lower(),
compose_files=compose_files)
return docker.compose
# return get_project(cls.find_compose_path(),
# project_name=cls.compose_project_name(),
# environment=env)

@classmethod
def find_compose_path(cls):
Expand All @@ -226,15 +239,15 @@ def find_compose_path(cls):

@classmethod
def get_service_log(cls, service):
container = cls.compose_project().containers(service_names=[service])[0]
container = cls.compose_project().ps(services=[service])[0]
return container.logs()

@classmethod
def service_log_contains(cls, service, msg):
log = cls.get_service_log(service)
counter = 0
for line in log.splitlines():
if line.find(msg.encode("utf-8")) >= 0:
if line.find(msg) >= 0:
counter += 1
return counter > 0

Expand Down
1 change: 1 addition & 0 deletions libbeat/tests/system/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
python-on-whales==0.70.1
async-timeout==4.0.3
attrs==19.3.0
autopep8==1.5.4
Expand Down
1 change: 1 addition & 0 deletions metricbeat/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ FROM golang:1.21.8
RUN \
apt update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -qq -y --no-install-recommends \
docker-compose \
netcat-openbsd \
python3 \
python3-dev \
Expand Down
6 changes: 6 additions & 0 deletions metricbeat/magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,20 @@ func GoIntegTest(ctx context.Context) error {
// Use PYTEST_ADDOPTS="-k pattern" to only run tests matching the specified pattern.
// Use any other PYTEST_* environment variable to influence the behavior of pytest.
func PythonIntegTest(ctx context.Context) error {
fmt.Printf("hi fae, starting PythonIntegTest\n")
if !devtools.IsInIntegTestEnv() {
fmt.Printf("hi fae, !IsInIntegTestEnv\n")
mg.SerialDeps(Fields, Dashboards)
} else {
fmt.Printf("hi fae, IsInIntegTestEnv\n")
}

passThroughEnvVars := append(
[]string{"ELASTICSEARCH_VERSION", "KIBANA_VERSION", "BEAT_VERSION"},
devtools.ListMatchingEnvVars("PYTEST_")...,
)
fmt.Printf("hi fae, env vars: %v\n", passThroughEnvVars)
//os.Exit(1)
runner, err := devtools.NewDockerIntegrationRunner(passThroughEnvVars...)
if err != nil {
return err
Expand Down
Loading