-
Notifications
You must be signed in to change notification settings - Fork 1
/
helpers.go
115 lines (99 loc) · 3.44 KB
/
helpers.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package dynamotest
import (
"context"
"testing"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
)
// NewDynamoDB creates a Docker container with DynamoDB Local, and returns the
// connected DynamoDB client. Clean up function is returned as well to ensure
// container gets removed after test is complete.
func NewDynamoDB(t testing.TB) (*dynamodb.Client, func()) {
t.Helper()
var dynamoClient *dynamodb.Client
pool, err := dockertest.NewPool("")
if err != nil {
t.Fatalf("Could not connect to docker: %s", err)
}
runOpt := &dockertest.RunOptions{
Repository: dynamoDBLocalRepo,
Tag: dynamoDBLocalTag,
PortBindings: map[docker.Port][]docker.PortBinding{
"0/tcp": {{HostIP: "localhost", HostPort: "8000/tcp"}},
},
}
resource, err := pool.RunWithOptions(runOpt)
if err != nil {
t.Fatalf("Could not start DynamoDB Local: %s", err)
}
t.Logf("Using host:port of '%s'", resource.GetHostPort("8000/tcp"))
if err = pool.Retry(func() error {
cfg, err := config.LoadDefaultConfig(context.Background(),
config.WithRegion("us-east-1"),
config.WithEndpointResolverWithOptions(
aws.EndpointResolverWithOptionsFunc(
func(service, region string, options ...interface{}) (aws.Endpoint, error) {
return aws.Endpoint{URL: "http://" + resource.GetHostPort("8000/tcp")}, nil
})),
config.WithCredentialsProvider(
credentials.StaticCredentialsProvider{
Value: aws.Credentials{
AccessKeyID: "dummy", SecretAccessKey: "dummy", SessionToken: "dummy",
Source: "Hard-coded credentials; values are irrelevant for local DynamoDB",
},
}),
)
if err != nil {
return err
}
dynamoClient = dynamodb.NewFromConfig(cfg)
return nil
}); err != nil {
t.Fatalf("Could not connect to the Docker instance of DynamoDB Local: %s", err)
}
return dynamoClient, func() {
if err = pool.Purge(resource); err != nil {
t.Fatalf("Could not purge DynamoDB: %s", err)
}
}
}
type InitialTableSetup struct {
Table *dynamodb.CreateTableInput
InitialData []*types.PutRequest
}
// PrepTable iterates the provided input, creates tables and put items.
func PrepTable(t testing.TB, client *dynamodb.Client, input ...InitialTableSetup) {
t.Helper()
// Add extra retry setup in case Docker instance is busy. This can happen
// especially within a CI environment, and the default retry count of 3
// times is too fragile.
opt := func(o *dynamodb.Options) { o.RetryMaxAttempts = 10 }
for _, i := range input {
_, err := client.CreateTable(context.Background(), i.Table, opt)
if err != nil {
t.Fatalf("Could not create table '%s': %v", *i.Table.TableName, err)
}
if len(i.InitialData) == 0 {
t.Logf("Table '%s' has been created, and no initial data has been added", *i.Table.TableName)
continue
}
puts := []types.WriteRequest{}
for _, d := range i.InitialData {
puts = append(puts, types.WriteRequest{PutRequest: d})
}
_, err = client.BatchWriteItem(context.Background(), &dynamodb.BatchWriteItemInput{
RequestItems: map[string][]types.WriteRequest{
*i.Table.TableName: puts,
},
})
if err != nil {
t.Fatalf("Could not write data to table '%s': %v", *i.Table.TableName, err)
}
t.Logf("Table '%s' has been created", *i.Table.TableName)
}
}