Skip to content

Commit 27ae331

Browse files
mergify[bot]michel-latermanycombinator
authored
[8.18](backport #4847) Update testing dependencies and fix issues with toxiproxy (#5500)
* Update testing dependencies and fix issues with toxiproxy (#4847) Update testing dependencies: toxiproxy image and library, go-testcontainers, and docker. Move toxiproxy container into docker network. (cherry picked from commit 4b4dbf2) # Conflicts: # testing/e2e/scaffold/scaffold.go # testing/e2e/stand_alone_test.go # testing/go.mod # testing/go.sum * Fixing conflicts --------- Co-authored-by: Michel Laterman <[email protected]> Co-authored-by: Shaunak Kashyap <[email protected]>
1 parent 2a3e7ad commit 27ae331

File tree

5 files changed

+145
-111
lines changed

5 files changed

+145
-111
lines changed

testing/e2e/scaffold/scaffold.go

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ import (
1919
"os"
2020
"path/filepath"
2121
"strings"
22+
"testing"
2223
"time"
2324

2425
"github.com/elastic/elastic-agent-client/v7/pkg/client"
2526

26-
toxiproxy "github.com/Shopify/toxiproxy/client"
2727
"github.com/stretchr/testify/suite"
2828
"github.com/testcontainers/testcontainers-go"
29-
"github.com/testcontainers/testcontainers-go/wait"
29+
toxitc "github.com/testcontainers/testcontainers-go/modules/toxiproxy"
3030
)
3131

3232
// Scaffold contains attributes and methods that are applicable to multiple test cases
@@ -516,34 +516,50 @@ func (s *Scaffold) FleetHasArtifacts(ctx context.Context) []ArtifactHit {
516516
}
517517
}
518518

519-
func (s *Scaffold) StartToxiproxy(ctx context.Context) *toxiproxy.Client {
520-
req := testcontainers.ContainerRequest{
521-
Image: "ghcr.io/shopify/toxiproxy:2.5.0",
522-
ExposedPorts: []string{"8474/tcp"},
523-
WaitingFor: wait.ForHTTP("/version").WithPort("8474/tcp"),
524-
NetworkMode: "host",
525-
}
526-
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
527-
ContainerRequest: req,
528-
Started: true,
529-
})
519+
type logger struct {
520+
*testing.T
521+
}
522+
523+
func (l *logger) Printf(format string, v ...interface{}) {
524+
l.Helper()
525+
l.Logf(format, v...)
526+
}
527+
528+
func (s *Scaffold) StartToxiproxy(ctx context.Context) *toxitc.Container {
529+
container, err := toxitc.Run(ctx, "ghcr.io/shopify/toxiproxy:2.12.0",
530+
testcontainers.CustomizeRequest(testcontainers.GenericContainerRequest{
531+
ContainerRequest: testcontainers.ContainerRequest{
532+
Hostname: "toxi",
533+
Name: "toxi",
534+
// Network is set to the integration test network instead of using host mode so it can easily communicate with other containers.
535+
// NOTE: the container will not become healthy when using `testcontainers-go 0.36.x+ if set to NetworkMode: "host"
536+
Networks: []string{"integration_default"},
537+
}}),
538+
testcontainers.WithLogger(&logger{s.T()}),
539+
toxitc.WithProxy("es", "elasticsearch:9200"),
540+
)
530541
s.Require().NoError(err)
531542

532543
s.T().Cleanup(func() {
533-
err := container.Terminate(context.Background())
544+
ctx, cancel := context.WithTimeout(context.Background(), time.Minute) // use context.Background instead of s.T().Context() because this is a cleanup task
545+
defer cancel()
546+
if s.T().Failed() {
547+
rc, err := container.Logs(ctx)
548+
if err != nil {
549+
s.T().Logf("unable to get proxy container logs: %v", err)
550+
} else {
551+
p, err := io.ReadAll(rc)
552+
s.T().Logf("failed test log read err: %v, proxy container logs:\n%s", err, string(p))
553+
rc.Close()
554+
}
555+
}
556+
err := container.Terminate(ctx)
534557
if err != nil {
535558
s.T().Log("could not terminate toxiproxy container")
536559
}
537560
})
538561

539-
mappedPort, err := container.MappedPort(ctx, "8474")
540-
s.Require().NoError(err)
541-
542-
hostIP, err := container.Host(ctx)
543-
s.Require().NoError(err)
544-
545-
endpoint := fmt.Sprintf("%s:%s", hostIP, mappedPort.Port())
546-
return toxiproxy.NewClient(endpoint)
562+
return container
547563
}
548564

549565
// HasTestStatusTrace will search elasticsearch for an APM trace to GET /api/status with labels.testName: name

testing/e2e/stand_alone_container_test.go

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ import (
1717

1818
"github.com/elastic/fleet-server/testing/e2e/scaffold"
1919

20-
toxiproxy "github.com/Shopify/toxiproxy/client"
21-
"github.com/docker/docker/api/types/container"
20+
toxiproxy "github.com/Shopify/toxiproxy/v2/client"
2221
"github.com/stretchr/testify/suite"
2322
"github.com/testcontainers/testcontainers-go"
2423

2524
"github.com/elastic/elastic-agent-client/v7/pkg/client"
2625
)
2726

27+
const fleetPort = "8220/tcp"
28+
2829
type StandAloneContainerSuite struct {
2930
scaffold.Scaffold
3031

@@ -85,12 +86,6 @@ func (suite *StandAloneContainerSuite) startFleetServer(ctx context.Context, opt
8586
f.Close()
8687
suite.Require().NoError(err)
8788

88-
networks := []string{"integration_default"}
89-
networkMode := container.NetworkMode(options.NetworkMode)
90-
if networkMode == "host" {
91-
networks = nil
92-
}
93-
9489
v, ok := os.LookupEnv("STANDALONE_E2E_IMAGE")
9590
suite.Require().True(ok, "expected STANDALONE_E2E_IMAGE to be defined")
9691
suite.dockerImg = v
@@ -99,9 +94,8 @@ func (suite *StandAloneContainerSuite) startFleetServer(ctx context.Context, opt
9994
req := testcontainers.ContainerRequest{
10095
Hostname: "fleet-server",
10196
Image: suite.dockerImg,
102-
ExposedPorts: []string{"8220/tcp"},
103-
Networks: networks,
104-
NetworkMode: networkMode,
97+
ExposedPorts: []string{fleetPort},
98+
Networks: []string{"integration_default"},
10599
Mounts: testcontainers.ContainerMounts{
106100
testcontainers.ContainerMount{
107101
Source: &testcontainers.GenericBindMountSource{configPath},
@@ -131,7 +125,7 @@ func (suite *StandAloneContainerSuite) TestHTTP() {
131125
},
132126
})
133127

134-
endpoint, err := suite.container.PortEndpoint(ctx, "8220/tcp", "http")
128+
endpoint, err := suite.container.PortEndpoint(ctx, fleetPort, "http")
135129
suite.Require().NoError(err)
136130

137131
suite.FleetServerStatusOK(ctx, endpoint)
@@ -143,30 +137,37 @@ func (suite *StandAloneContainerSuite) TestWithElasticsearchConnectionFailures()
143137
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
144138
defer cancel()
145139

146-
proxy, err := suite.StartToxiproxy(ctx).CreateProxy("es", "localhost:0", suite.ESHosts)
140+
proxyContainer := suite.StartToxiproxy(ctx)
141+
proxyEndpoint, err := proxyContainer.URI(ctx)
147142
suite.Require().NoError(err)
143+
proxyClient := toxiproxy.NewClient(proxyEndpoint)
148144

149145
suite.startFleetServer(ctx, standaloneContainerOptions{
150-
Template: "stand-alone-http.tpl",
151-
NetworkMode: "host",
146+
Template: "stand-alone-http.tpl",
152147
TemplateData: map[string]string{
153-
"Hosts": "http://" + proxy.Listen,
148+
"Hosts": "http://toxi:8666", // Toxiproxy ports start at 8666, fleet-server starts in the integration test network and can use the port directly.
154149
"ServiceToken": suite.ServiceToken,
155150
},
156151
})
157152

153+
endpoint, err := suite.container.PortEndpoint(ctx, fleetPort, "http")
154+
suite.Require().NoError(err)
155+
158156
// Wait to check that it is healthy.
159-
suite.FleetServerStatusIs(ctx, "http://localhost:8220", client.UnitStateHealthy)
157+
suite.FleetServerStatusIs(ctx, endpoint, client.UnitStateHealthy)
158+
159+
proxy, err := proxyClient.Proxy("es")
160+
suite.Require().NoError(err)
160161

161162
// Provoke timeouts and wait for the healthcheck to fail.
162163
_, err = proxy.AddToxic("force_timeout", "timeout", "upstream", 1.0, toxiproxy.Attributes{})
163164
suite.Require().NoError(err)
164-
suite.FleetServerStatusIs(ctx, "http://localhost:8220", client.UnitStateDegraded)
165+
suite.FleetServerStatusIs(ctx, endpoint, client.UnitStateDegraded)
165166

166167
// Recover the network and wait for the healthcheck to be healthy again.
167168
err = proxy.RemoveToxic("force_timeout")
168169
suite.Require().NoError(err)
169-
suite.FleetServerStatusIs(ctx, "http://localhost:8220", client.UnitStateHealthy)
170+
suite.FleetServerStatusIs(ctx, endpoint, client.UnitStateHealthy)
170171
}
171172

172173
func (suite *StandAloneContainerSuite) TestAPMInstrumentation() {
@@ -183,7 +184,7 @@ func (suite *StandAloneContainerSuite) TestAPMInstrumentation() {
183184
},
184185
})
185186

186-
endpoint, err := suite.container.PortEndpoint(ctx, "8220/tcp", "http")
187+
endpoint, err := suite.container.PortEndpoint(ctx, fleetPort, "http")
187188
suite.Require().NoError(err)
188189

189190
suite.FleetServerStatusOK(ctx, endpoint)

testing/e2e/stand_alone_test.go

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020
"testing"
2121
"time"
2222

23-
toxiproxy "github.com/Shopify/toxiproxy/client"
23+
toxiproxy "github.com/Shopify/toxiproxy/v2/client"
2424
"github.com/stretchr/testify/suite"
2525

2626
"github.com/elastic/elastic-agent-client/v7/pkg/client"
@@ -105,7 +105,12 @@ func (suite *StandAloneSuite) TestHTTP() {
105105
func (suite *StandAloneSuite) TestWithElasticsearchConnectionFailures() {
106106
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
107107

108-
proxy, err := suite.StartToxiproxy(ctx).CreateProxy("es", "localhost:0", suite.ESHosts)
108+
proxyContainer := suite.StartToxiproxy(ctx)
109+
proxyEndpoint, err := proxyContainer.URI(ctx)
110+
suite.Require().NoError(err)
111+
proxyClient := toxiproxy.NewClient(proxyEndpoint)
112+
113+
pHost, pPort, err := proxyContainer.ProxiedEndpoint(8666) // Toxiproxy port starts at 8666
109114
suite.Require().NoError(err)
110115

111116
// Create a config file from a template in the test temp dir
@@ -115,7 +120,7 @@ func (suite *StandAloneSuite) TestWithElasticsearchConnectionFailures() {
115120
f, err := os.Create(filepath.Join(dir, "config.yml"))
116121
suite.Require().NoError(err)
117122
err = tpl.Execute(f, map[string]string{
118-
"Hosts": "http://" + proxy.Listen,
123+
"Hosts": fmt.Sprintf("http://%s:%s", pHost, pPort),
119124
"ServiceToken": suite.ServiceToken,
120125
})
121126
f.Close()
@@ -134,6 +139,8 @@ func (suite *StandAloneSuite) TestWithElasticsearchConnectionFailures() {
134139
suite.FleetServerStatusIs(ctx, "http://localhost:8220", client.UnitStateHealthy)
135140

136141
// Provoke timeouts and wait for the healthcheck to fail.
142+
proxy, err := proxyClient.Proxy("es")
143+
suite.Require().NoError(err)
137144
_, err = proxy.AddToxic("force_timeout", "timeout", "upstream", 1.0, toxiproxy.Attributes{})
138145
suite.Require().NoError(err)
139146
suite.FleetServerStatusIs(ctx, "http://localhost:8220", client.UnitStateDegraded)
@@ -430,19 +437,26 @@ func (suite *StandAloneSuite) TestElasticsearch503OnEnroll() {
430437
func (suite *StandAloneSuite) TestElasticsearchTimeoutOnStartup() {
431438
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
432439

433-
proxy, err := suite.StartToxiproxy(ctx).CreateProxy("es", "localhost:0", suite.ESHosts)
440+
proxyContainer := suite.StartToxiproxy(ctx)
441+
proxyEndpoint, err := proxyContainer.URI(ctx)
442+
suite.Require().NoError(err)
443+
proxyClient := toxiproxy.NewClient(proxyEndpoint)
444+
proxy, err := proxyClient.Proxy("es")
434445
suite.Require().NoError(err)
435446
_, err = proxy.AddToxic("force_timeout", "timeout", "upstream", 1.0, toxiproxy.Attributes{})
436447
suite.Require().NoError(err)
437448

449+
pHost, pPort, err := proxyContainer.ProxiedEndpoint(8666) // Toxiproxy port starts at 8666
450+
suite.Require().NoError(err)
451+
438452
// Create a config file from a template in the test temp dir
439453
dir := suite.T().TempDir()
440454
tpl, err := template.ParseFiles(filepath.Join("testdata", "stand-alone-http.tpl"))
441455
suite.Require().NoError(err)
442456
f, err := os.Create(filepath.Join(dir, "config.yml"))
443457
suite.Require().NoError(err)
444458
err = tpl.Execute(f, map[string]string{
445-
"Hosts": "http://" + proxy.Listen,
459+
"Hosts": fmt.Sprintf("http://%s:%s", pHost, pPort),
446460
"ServiceToken": suite.ServiceToken,
447461
})
448462
f.Close()

testing/go.mod

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,22 @@ replace (
88
)
99

1010
require (
11-
github.com/Shopify/toxiproxy v2.1.4+incompatible
12-
github.com/docker/docker v28.4.0+incompatible
11+
github.com/Shopify/toxiproxy/v2 v2.12.0
12+
github.com/docker/docker v28.1.1+incompatible
1313
github.com/elastic/elastic-agent-client/v7 v7.17.2
1414
github.com/elastic/fleet-server/pkg/api v0.0.0-00010101000000-000000000000
1515
github.com/elastic/fleet-server/v7 v7.0.0-00010101000000-000000000000
1616
github.com/stretchr/testify v1.11.1
17-
github.com/testcontainers/testcontainers-go v0.38.0
17+
github.com/testcontainers/testcontainers-go v0.37.0
18+
github.com/testcontainers/testcontainers-go/modules/toxiproxy v0.37.0
1819
)
1920

2021
require (
2122
dario.cat/mergo v1.0.1 // indirect
22-
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
23+
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
2324
github.com/Microsoft/go-winio v0.6.2 // indirect
2425
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
25-
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
26-
github.com/containerd/errdefs v1.0.0 // indirect
27-
github.com/containerd/errdefs/pkg v0.3.0 // indirect
26+
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
2827
github.com/containerd/log v0.1.0 // indirect
2928
github.com/containerd/platforms v0.2.1 // indirect
3029
github.com/cpuguy83/dockercfg v0.3.2 // indirect
@@ -38,43 +37,43 @@ require (
3837
github.com/go-logr/logr v1.4.3 // indirect
3938
github.com/go-logr/stdr v1.2.2 // indirect
4039
github.com/go-ole/go-ole v1.3.0 // indirect
40+
github.com/gogo/protobuf v1.3.2 // indirect
4141
github.com/google/uuid v1.6.0 // indirect
42+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
4243
github.com/klauspost/compress v1.18.0 // indirect
43-
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
44+
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
4445
github.com/magiconair/properties v1.8.10 // indirect
46+
github.com/mattn/go-colorable v0.1.14 // indirect
4547
github.com/moby/docker-image-spec v1.3.1 // indirect
4648
github.com/moby/go-archive v0.1.0 // indirect
4749
github.com/moby/patternmatcher v0.6.0 // indirect
50+
github.com/moby/sys/atomicwriter v0.1.0 // indirect
4851
github.com/moby/sys/sequential v0.6.0 // indirect
4952
github.com/moby/sys/user v0.4.0 // indirect
5053
github.com/moby/sys/userns v0.1.0 // indirect
51-
github.com/moby/term v0.5.0 // indirect
54+
github.com/moby/term v0.5.2 // indirect
5255
github.com/morikuni/aec v1.0.0 // indirect
5356
github.com/oapi-codegen/runtime v1.1.1 // indirect
5457
github.com/opencontainers/go-digest v1.0.0 // indirect
5558
github.com/opencontainers/image-spec v1.1.1 // indirect
5659
github.com/pkg/errors v0.9.1 // indirect
5760
github.com/pmezard/go-difflib v1.0.0 // indirect
58-
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
61+
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
62+
github.com/prometheus/procfs v0.16.1 // indirect
5963
github.com/shirou/gopsutil/v4 v4.25.5 // indirect
6064
github.com/sirupsen/logrus v1.9.3 // indirect
61-
github.com/tklauser/go-sysconf v0.3.12 // indirect
62-
github.com/tklauser/numcpus v0.6.1 // indirect
65+
github.com/tklauser/go-sysconf v0.3.15 // indirect
66+
github.com/tklauser/numcpus v0.10.0 // indirect
6367
github.com/yusufpapurcu/wmi v1.2.4 // indirect
6468
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
65-
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
69+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
6670
go.opentelemetry.io/otel v1.37.0 // indirect
67-
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect
6871
go.opentelemetry.io/otel/metric v1.37.0 // indirect
6972
go.opentelemetry.io/otel/trace v1.37.0 // indirect
7073
golang.org/x/crypto v0.41.0 // indirect
71-
golang.org/x/mod v0.26.0 // indirect
7274
golang.org/x/net v0.43.0 // indirect
73-
golang.org/x/sync v0.16.0 // indirect
7475
golang.org/x/sys v0.35.0 // indirect
7576
golang.org/x/text v0.28.0 // indirect
76-
golang.org/x/tools v0.35.0 // indirect
77-
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
7877
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
7978
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
8079
google.golang.org/grpc v1.75.0 // indirect

0 commit comments

Comments
 (0)