Skip to content

Commit c412150

Browse files
authored
S3 tests: use testcontainers (#79)
* S3 tests: use testcontainers Remove internal s3testing package in favour of testcontainers, as suggested in #61. * s3 tests: skip tests based on testcontainers if no provider
1 parent 1cbae45 commit c412150

File tree

8 files changed

+257
-203
lines changed

8 files changed

+257
-203
lines changed

backends/s3/credentials_test.go

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ import (
99
"time"
1010

1111
"github.com/PowerDNS/simpleblob/backends/s3"
12-
"github.com/PowerDNS/simpleblob/backends/s3/s3testing"
1312
"github.com/PowerDNS/simpleblob/tester"
1413
"github.com/minio/minio-go/v7"
1514
"github.com/minio/minio-go/v7/pkg/credentials"
15+
"github.com/testcontainers/testcontainers-go"
16+
testcontainersminio "github.com/testcontainers/testcontainers-go/modules/minio"
1617
)
1718

1819
func TestFileSecretsCredentials(t *testing.T) {
20+
testcontainers.SkipIfProviderIsNotHealthy(t)
1921
tempDir := t.TempDir()
2022

2123
access, secret := secretsPaths(tempDir)
@@ -30,15 +32,20 @@ func TestFileSecretsCredentials(t *testing.T) {
3032
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
3133
defer cancel()
3234

33-
// Create server
34-
addr, stop, err := s3testing.ServeMinio(ctx, tempDir)
35-
if errors.Is(err, s3testing.ErrMinioNotFound) {
36-
t.Skip("minio binary not found locally, make sure it is in PATH")
35+
container, err := testcontainersminio.Run(ctx, "quay.io/minio/minio")
36+
if err != nil {
37+
t.Fatal(err)
3738
}
39+
defer func() {
40+
if err := container.Terminate(ctx); err != nil {
41+
t.Log(err)
42+
}
43+
}()
44+
45+
addr, err := container.ConnectionString(ctx)
3846
if err != nil {
3947
t.Fatal(err)
4048
}
41-
defer func() { _ = stop() }()
4249

4350
// Create minio client, using our provider.
4451
creds := credentials.New(provider)
@@ -65,7 +72,7 @@ func TestFileSecretsCredentials(t *testing.T) {
6572
// First credential files creation.
6673
// Keep them empty for now,
6774
// so that calls to the server will fail.
68-
writeSecrets(t, tempDir, "")
75+
writeSecrets(t, tempDir, "", "")
6976

7077
// The files do not hold the right values,
7178
// so a call to the server should fail.
@@ -74,31 +81,38 @@ func TestFileSecretsCredentials(t *testing.T) {
7481
// Write the right keys to the files.
7582
// We're not testing expiry here,
7683
// and forcing credentials cache to update.
77-
writeSecrets(t, tempDir, s3testing.AdminUserOrPassword)
84+
writeSecrets(t, tempDir, container.Username, container.Password)
7885
creds.Expire()
7986
assertClientSuccess(true, "after changing files content")
8087

8188
// Change content of the files.
82-
writeSecrets(t, tempDir, "badcredentials")
89+
writeSecrets(t, tempDir, "bad-user", "bad-password")
8390
creds.Expire()
8491
assertClientSuccess(false, "after changing again, to bad credentials")
8592
}
8693

8794
func TestBackendWithSecrets(t *testing.T) {
95+
testcontainers.SkipIfProviderIsNotHealthy(t)
8896
tempDir := t.TempDir()
8997

9098
ctx := context.Background()
9199
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
92100
defer cancel()
93101

94-
addr, stop, err := s3testing.ServeMinio(ctx, tempDir)
95-
if errors.Is(err, s3testing.ErrMinioNotFound) {
96-
t.Skip("minio binary not found locally, make sure it is in PATH")
102+
container, err := testcontainersminio.Run(ctx, "quay.io/minio/minio")
103+
if err != nil {
104+
t.Fatal(err)
97105
}
106+
defer func() {
107+
if err := container.Terminate(ctx); err != nil {
108+
t.Log(err)
109+
}
110+
}()
111+
112+
addr, err := container.ConnectionString(ctx)
98113
if err != nil {
99114
t.Fatal(err)
100115
}
101-
defer func() { _ = stop() }()
102116

103117
// Prepare backend options to reuse.
104118
// These will not change.
@@ -119,15 +133,15 @@ func TestBackendWithSecrets(t *testing.T) {
119133
}
120134

121135
// Now write files, but with bad content.
122-
writeSecrets(t, tempDir, "")
136+
writeSecrets(t, tempDir, "", "")
123137
_, err = s3.New(ctx, opt)
124138
if err == nil || err.Error() != "Access Denied." {
125139
t.Fatal("backend should not start with bad credentials")
126140
}
127141

128142
// Write the good content.
129143
// Now the backend should start and be able to perform a request.
130-
writeSecrets(t, tempDir, s3testing.AdminUserOrPassword)
144+
writeSecrets(t, tempDir, container.Username, container.Password)
131145

132146
backend, err := s3.New(ctx, opt)
133147
if err != nil {
@@ -153,14 +167,13 @@ func secretsPaths(dir string) (access, secret string) {
153167

154168
// writeSecrets writes content to files called "access-key" and "secret-key"
155169
// in dir.
156-
// It returns
157-
func writeSecrets(t testing.TB, dir, content string) {
170+
func writeSecrets(t testing.TB, dir, adminUser, password string) {
158171
access, secret := secretsPaths(dir)
159-
err := os.WriteFile(access, []byte(content), 0666)
172+
err := os.WriteFile(access, []byte(adminUser), 0666)
160173
if err != nil {
161174
t.Fatal(err)
162175
}
163-
err = os.WriteFile(secret, []byte(content), 0666)
176+
err = os.WriteFile(secret, []byte(password), 0666)
164177
if err != nil {
165178
t.Fatal(err)
166179
}

backends/s3/s3_test.go

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,40 @@ package s3
22

33
import (
44
"context"
5-
"os"
65
"testing"
76
"time"
87

98
"github.com/minio/minio-go/v7"
109
"github.com/stretchr/testify/assert"
1110
"github.com/stretchr/testify/require"
12-
"gopkg.in/yaml.v2"
11+
"github.com/testcontainers/testcontainers-go"
12+
testcontainersminio "github.com/testcontainers/testcontainers-go/modules/minio"
1313

1414
"github.com/PowerDNS/simpleblob/tester"
1515
)
1616

17-
// TestConfigPathEnv is the path to a YAML file with the Options
18-
// with an S3 bucket configuration that can be used for testing.
19-
// The bucket will be emptied before every run!!!
20-
//
21-
// To run a Minio for this :
22-
//
23-
// env MINIO_ROOT_USER=test MINIO_ROOT_PASSWORD=secret minio server /tmp/test-data/
24-
//
25-
// Example test config:
26-
//
27-
// {
28-
// "access_key": "test",
29-
// "secret_key": "verysecret",
30-
// "region": "us-east-1",
31-
// "bucket": "test-bucket",
32-
// "endpoint_url": "http://127.0.0.1:9000"
33-
// }
34-
const TestConfigPathEnv = "SIMPLEBLOB_TEST_S3_CONFIG"
35-
3617
func getBackend(ctx context.Context, t *testing.T) (b *Backend) {
37-
cfgPath := os.Getenv(TestConfigPathEnv)
38-
if cfgPath == "" {
39-
t.Skipf("S3 tests skipped, set the %s env var to run these", TestConfigPathEnv)
40-
return
18+
testcontainers.SkipIfProviderIsNotHealthy(t)
19+
container, err := testcontainersminio.Run(ctx, "quay.io/minio/minio")
20+
if err != nil {
21+
t.Fatal(err)
4122
}
4223

43-
cfgContents, err := os.ReadFile(cfgPath)
44-
require.NoError(t, err)
45-
46-
var opt Options
47-
err = yaml.Unmarshal(cfgContents, &opt)
48-
require.NoError(t, err)
24+
url, err := container.ConnectionString(ctx)
25+
if err != nil {
26+
t.Fatal(err)
27+
}
4928

50-
b, err = New(ctx, opt)
29+
b, err = New(ctx, Options{
30+
EndpointURL: "http://" + url,
31+
AccessKey: container.Username,
32+
SecretKey: container.Password,
33+
Bucket: "test-bucket",
34+
CreateBucket: true,
35+
})
5136
require.NoError(t, err)
5237

53-
cleanup := func() {
54-
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
55-
defer cancel()
56-
38+
cleanStorage := func(ctx context.Context) {
5739
blobs, err := b.List(ctx, "")
5840
if err != nil {
5941
t.Logf("Blobs list error: %s", err)
@@ -69,8 +51,15 @@ func getBackend(ctx context.Context, t *testing.T) (b *Backend) {
6951
err = b.client.RemoveObject(ctx, b.opt.Bucket, b.markerName, minio.RemoveObjectOptions{})
7052
require.NoError(t, err)
7153
}
72-
t.Cleanup(cleanup)
73-
cleanup()
54+
t.Cleanup(func() {
55+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
56+
defer cancel()
57+
cleanStorage(ctx)
58+
if err := container.Terminate(ctx); err != nil {
59+
t.Log(err)
60+
}
61+
})
62+
cleanStorage(ctx)
7463

7564
return b
7665
}

backends/s3/s3testing/minio.go

Lines changed: 0 additions & 73 deletions
This file was deleted.

backends/s3/s3testing/port.go

Lines changed: 0 additions & 14 deletions
This file was deleted.

go.mod

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,67 @@ require (
1010
github.com/minio/minio-go/v7 v7.0.78
1111
github.com/prometheus/client_golang v1.20.4
1212
github.com/stretchr/testify v1.9.0
13+
github.com/testcontainers/testcontainers-go v0.33.0
14+
github.com/testcontainers/testcontainers-go/modules/minio v0.33.0
1315
gopkg.in/yaml.v2 v2.4.0
1416
)
1517

1618
require (
19+
dario.cat/mergo v1.0.0 // indirect
20+
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
21+
github.com/Microsoft/go-winio v0.6.2 // indirect
1722
github.com/beorn7/perks v1.0.1 // indirect
23+
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
1824
github.com/cespare/xxhash/v2 v2.3.0 // indirect
25+
github.com/containerd/containerd v1.7.18 // indirect
26+
github.com/containerd/log v0.1.0 // indirect
27+
github.com/containerd/platforms v0.2.1 // indirect
28+
github.com/cpuguy83/dockercfg v0.3.1 // indirect
1929
github.com/davecgh/go-spew v1.1.1 // indirect
30+
github.com/distribution/reference v0.6.0 // indirect
31+
github.com/docker/docker v27.1.1+incompatible // indirect
32+
github.com/docker/go-connections v0.5.0 // indirect
33+
github.com/docker/go-units v0.5.0 // indirect
2034
github.com/dustin/go-humanize v1.0.1 // indirect
35+
github.com/felixge/httpsnoop v1.0.4 // indirect
2136
github.com/go-ini/ini v1.67.0 // indirect
37+
github.com/go-logr/stdr v1.2.2 // indirect
38+
github.com/go-ole/go-ole v1.2.6 // indirect
2239
github.com/goccy/go-json v0.10.3 // indirect
40+
github.com/gogo/protobuf v1.3.2 // indirect
2341
github.com/google/uuid v1.6.0 // indirect
2442
github.com/klauspost/compress v1.17.11 // indirect
2543
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
2644
github.com/kr/text v0.2.0 // indirect
45+
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
46+
github.com/magiconair/properties v1.8.7 // indirect
2747
github.com/minio/md5-simd v1.1.2 // indirect
48+
github.com/moby/docker-image-spec v1.3.1 // indirect
49+
github.com/moby/patternmatcher v0.6.0 // indirect
50+
github.com/moby/sys/sequential v0.5.0 // indirect
51+
github.com/moby/sys/user v0.1.0 // indirect
52+
github.com/moby/term v0.5.0 // indirect
53+
github.com/morikuni/aec v1.0.0 // indirect
2854
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
55+
github.com/opencontainers/go-digest v1.0.0 // indirect
56+
github.com/opencontainers/image-spec v1.1.0 // indirect
57+
github.com/pkg/errors v0.9.1 // indirect
2958
github.com/pmezard/go-difflib v1.0.0 // indirect
59+
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
3060
github.com/prometheus/client_model v0.6.1 // indirect
3161
github.com/prometheus/common v0.55.0 // indirect
3262
github.com/prometheus/procfs v0.15.1 // indirect
3363
github.com/rs/xid v1.6.0 // indirect
64+
github.com/shirou/gopsutil/v3 v3.23.12 // indirect
65+
github.com/shoenig/go-m1cpu v0.1.6 // indirect
66+
github.com/sirupsen/logrus v1.9.3 // indirect
67+
github.com/tklauser/go-sysconf v0.3.12 // indirect
68+
github.com/tklauser/numcpus v0.6.1 // indirect
69+
github.com/yusufpapurcu/wmi v1.2.3 // indirect
70+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
71+
go.opentelemetry.io/otel v1.24.0 // indirect
72+
go.opentelemetry.io/otel/metric v1.24.0 // indirect
73+
go.opentelemetry.io/otel/trace v1.24.0 // indirect
3474
golang.org/x/crypto v0.28.0 // indirect
3575
golang.org/x/net v0.30.0 // indirect
3676
golang.org/x/sys v0.26.0 // indirect

0 commit comments

Comments
 (0)