Skip to content

Commit

Permalink
chore: use new container request customisation in localstack
Browse files Browse the repository at this point in the history
  • Loading branch information
mdelapenya committed Mar 28, 2023
1 parent 080ea44 commit 376dc26
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 54 deletions.
18 changes: 6 additions & 12 deletions docs/modules/localstack.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Running LocalStack as a stand-in for multiple AWS services during a test:
<!--/codeinclude-->

Environment variables listed in [Localstack's README](https://github.com/localstack/localstack#configurations) may be used to customize Localstack's configuration.
Use the `OverrideContainerRequest` option when creating the `LocalStackContainer` to apply configuration settings.
Use the `testcontainers.CustomizeContainerRequest` option when creating the LocalStack `Container` to apply configuration settings.

## Creating a client using the AWS SDK for Go

Expand Down Expand Up @@ -64,34 +64,28 @@ Testcontainers will inform Localstack of the best hostname automatically, using
The LocalStack module exposes one single function to create the LocalStack container, and this function receives two parameters:

```golang
func StartContainer(ctx context.Context, overrideReq OverrideContainerRequestOption) (*LocalStackContainer, error)
func RunContainer(ctx context.Context, opts ...testcontainers.CustomizeContainerRequestOption) (*Container, error) {
```
- `context.Context`
- `OverrideContainerRequestOption`
- `testcontainers.CustomizeContainerRequestOption`
### OverrideContainerRequestOption
### CustomizeContainerRequestOption
The `OverrideContainerRequestOption` functional option represents a way to override the default LocalStack container request:
The variadic `testcontainers.CustomizeContainerRequestOption` functional option represents a way to override the default LocalStack container request:
<!--codeinclude-->
[Default container request](../../modules/localstack/localstack.go) inside_block:defaultContainerRequest
<!--/codeinclude-->
With simply passing your own instance of an `OverrideContainerRequestOption` type to the `StartContainer` function, you'll be able to configure the LocalStack container with your own needs, as this new container request will be merged with the original one.
With simply passing your own instance of an `testcontainers.CustomizeContainerRequest` type to the `RunContainer` function, you'll be able to configure the LocalStack container with your own needs, as this new container request will be merged with the original one.
In the following example you check how it's possible to set certain environment variables that are needed by the tests, the most important of them the AWS services you want to use. Besides, the container runs in a separate Docker network with an alias:
<!--codeinclude-->
[Overriding the default container request](../../modules/localstack/localstack_test.go) inside_block:withNetwork
<!--/codeinclude-->
If you do not need to override the container request, you can pass `nil` or the `NoopOverrideContainerRequest` instance, which is exposed as a helper for this reason.

<!--codeinclude-->
[Skip overriding the default container request](../../modules/localstack/localstack_test.go) inside_block:noopOverrideContainerRequest
<!--/codeinclude-->

## Testing the module
The module includes unit and integration tests that can be run from its source code. To run the tests please execute the following command:
Expand Down
22 changes: 14 additions & 8 deletions modules/localstack/localstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ func isLegacyMode(image string) bool {
return true
}

// StartContainer creates an instance of the LocalStack container type, being possible to pass a custom request and options:
// RunContainer creates an instance of the LocalStack container type, being possible to pass a custom request and options:
// - overrideReq: a function that can be used to override the default container request, usually used to set the image version, environment variables for localstack, etc.
func StartContainer(ctx context.Context, overrideReq OverrideContainerRequestOption) (*LocalStackContainer, error) {
func RunContainer(ctx context.Context, opts ...testcontainers.CustomizeContainerRequestOption) (*Container, error) {
// defaultContainerRequest {
req := testcontainers.ContainerRequest{
Image: fmt.Sprintf("localstack/localstack:%s", defaultVersion),
Expand All @@ -53,14 +53,13 @@ func StartContainer(ctx context.Context, overrideReq OverrideContainerRequestOpt
}
// }

localStackReq := LocalStackContainerRequest{
localStackReq := ContainerRequest{
ContainerRequest: req,
}

// first, when needed, we merge the user request with the default one
if overrideReq != nil {
merged := overrideReq(localStackReq.ContainerRequest)
localStackReq.ContainerRequest = merged
for _, opt := range opts {
localStackReq.ContainerRequest = opt(localStackReq.ContainerRequest)
}

if isLegacyMode(localStackReq.Image) {
Expand All @@ -81,13 +80,20 @@ func StartContainer(ctx context.Context, overrideReq OverrideContainerRequestOpt
return nil, err
}

c := &LocalStackContainer{
c := &Container{
Container: container,
}
return c, nil
}

func configureDockerHost(req *LocalStackContainerRequest) (reason string, err error) {
// StartContainer creates an instance of the LocalStack container type, being possible to pass a custom request and options:
// - overrideReq: a function that can be used to override the default container request, usually used to set the image version, environment variables for localstack, etc.
// Deprecated use RunContainer instead
func StartContainer(ctx context.Context, overrideReq OverrideContainerRequestOption) (*Container, error) {
return RunContainer(ctx, testcontainers.CustomizeContainerRequestOption(overrideReq))
}

func configureDockerHost(req *ContainerRequest) (reason string, err error) {
err = nil
reason = ""

Expand Down
25 changes: 10 additions & 15 deletions modules/localstack/localstack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
"github.com/testcontainers/testcontainers-go"
)

func generateContainerRequest() *LocalStackContainerRequest {
return &LocalStackContainerRequest{
func generateContainerRequest() *ContainerRequest {
return &ContainerRequest{
ContainerRequest: testcontainers.ContainerRequest{
Env: map[string]string{},
ExposedPorts: []string{},
Expand Down Expand Up @@ -91,13 +91,13 @@ func TestIsLegacyMode(t *testing.T) {
}
}

func TestStart(t *testing.T) {
func TestRunContainer(t *testing.T) {
ctx := context.Background()

// withoutNetwork {
container, err := StartContainer(
container, err := RunContainer(
ctx,
OverrideContainerRequest(testcontainers.ContainerRequest{
testcontainers.CustomizeContainerRequest(testcontainers.ContainerRequest{
Image: fmt.Sprintf("localstack/localstack:%s", defaultVersion),
}),
)
Expand All @@ -122,20 +122,15 @@ func TestStart(t *testing.T) {
})
}

func TestStartWithoutOverride(t *testing.T) {
// noopOverrideContainerRequest {
func TestRunContainerWithoutOverride(t *testing.T) {
ctx := context.Background()

container, err := StartContainer(
ctx,
NoopOverrideContainerRequest,
)
container, err := RunContainer(ctx)
require.Nil(t, err)
assert.NotNil(t, container)
// }
}

func TestStartWithNetwork(t *testing.T) {
func TestRunContainerWithNetwork(t *testing.T) {
// withNetwork {
ctx := context.Background()

Expand All @@ -147,9 +142,9 @@ func TestStartWithNetwork(t *testing.T) {
require.Nil(t, err)
assert.NotNil(t, nw)

container, err := StartContainer(
container, err := RunContainer(
ctx,
OverrideContainerRequest(testcontainers.ContainerRequest{
testcontainers.CustomizeContainerRequest(testcontainers.ContainerRequest{
Image: "localstack/localstack:0.13.0",
Env: map[string]string{"SERVICES": "s3,sqs"},
Networks: []string{"localstack-network"},
Expand Down
33 changes: 18 additions & 15 deletions modules/localstack/types.go
Original file line number Diff line number Diff line change
@@ -1,40 +1,43 @@
package localstack

import (
"fmt"

"github.com/imdario/mergo"
"github.com/testcontainers/testcontainers-go"
)

// LocalStackContainer represents the LocalStack container type used in the module
type LocalStackContainer struct {
// Container represents the LocalStack container type used in the module
type Container struct {
testcontainers.Container
}

// LocalStackContainerRequest represents the LocalStack container request type used in the module
// Deprecated: use Container instead
type LocalStackContainer struct {
Container
}

// ContainerRequest represents the LocalStack container request type used in the module
// to configure the container
type LocalStackContainerRequest struct {
type ContainerRequest struct {
testcontainers.ContainerRequest
}

// Deprecated: use ContainerRequest instead
type LocalStackContainerRequest struct {
ContainerRequest
}

// OverrideContainerRequestOption is a type that can be used to configure the Testcontainers container request.
// The passed request will be merged with the default one.
// Deprecated: use testcontainers.CustomizeContainerRequestOption instead
type OverrideContainerRequestOption func(req testcontainers.ContainerRequest) testcontainers.ContainerRequest

// NoopOverrideContainerRequest returns a helper function that does not override the container request
// Deprecated
var NoopOverrideContainerRequest = func(req testcontainers.ContainerRequest) testcontainers.ContainerRequest {
return req
}

// OverrideContainerRequest returns a function that can be used to merge the passed container request with one that is created by the LocalStack container
// Deprecated: use testcontainers.CustomizeContainerRequestOption instead
func OverrideContainerRequest(r testcontainers.ContainerRequest) func(req testcontainers.ContainerRequest) testcontainers.ContainerRequest {
return func(req testcontainers.ContainerRequest) testcontainers.ContainerRequest {
if err := mergo.Merge(&req, r, mergo.WithOverride); err != nil {
fmt.Printf("error merging container request %v. Keeping the default one: %v", err, req)
return req
}

return req
}
return testcontainers.CustomizeContainerRequest(r)
}
4 changes: 2 additions & 2 deletions modules/localstack/v1/s3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const (
// awsSDKClientV1 {
// awsSession returns a new AWS session for the given service. To retrieve the specific AWS service client, use the
// session's client method, e.g. s3manager.NewUploader(session).
func awsSession(ctx context.Context, l *localstack.LocalStackContainer) (*session.Session, error) {
func awsSession(ctx context.Context, l *localstack.Container) (*session.Session, error) {
mappedPort, err := l.MappedPort(ctx, nat.Port("4566/tcp"))
if err != nil {
return &session.Session{}, err
Expand Down Expand Up @@ -62,7 +62,7 @@ func TestS3(t *testing.T) {
ctx := context.Background()

// localStackCreateContainer {
container, err := localstack.StartContainer(ctx, localstack.NoopOverrideContainerRequest)
container, err := localstack.RunContainer(ctx)
require.Nil(t, err)
// }

Expand Down
4 changes: 2 additions & 2 deletions modules/localstack/v2/s3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const (
)

// awsSDKClientV2 {
func s3Client(ctx context.Context, l *localstack.LocalStackContainer) (*s3.Client, error) {
func s3Client(ctx context.Context, l *localstack.Container) (*s3.Client, error) {
mappedPort, err := l.MappedPort(ctx, nat.Port("4566/tcp"))
if err != nil {
return nil, err
Expand Down Expand Up @@ -72,7 +72,7 @@ func s3Client(ctx context.Context, l *localstack.LocalStackContainer) (*s3.Clien
func TestS3(t *testing.T) {
ctx := context.Background()

container, err := localstack.StartContainer(ctx, localstack.NoopOverrideContainerRequest)
container, err := localstack.RunContainer(ctx)
require.Nil(t, err)

s3Client, err := s3Client(ctx, container)
Expand Down

0 comments on commit 376dc26

Please sign in to comment.