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

feat: support generating Go modules or example modules #826

Merged
merged 20 commits into from
Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ updates:
interval: weekly
open-pull-requests-limit: 3
rebase-strategy: disabled
- package-ecosystem: gomod
directory: /modulegen
schedule:
interval: weekly
open-pull-requests-limit: 3
rebase-strategy: disabled
- package-ecosystem: gomod
directory: /modules/compose
schedule:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ jobs:
if: ${{ matrix.platform == 'ubuntu-latest' }}
run: make test-unit

- name: Run example generator tests
- name: Run module generator tests
if: ${{ matrix.platform == 'ubuntu-latest' }}
run: make -C examples test-unit
run: make -C modulegen test-unit

- name: Run checker
run: |
Expand Down
38 changes: 4 additions & 34 deletions docs/examples/index.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,12 @@
# Code examples

In this section you'll discover how to create code examples for _Testcontainers for Go_.
In this section you'll discover how to create code examples for _Testcontainers for Go_, which are almost the same as Go modules, but without exporting any public API.

## Interested in adding a new example?

We have provided a command line tool to generate the scaffolding for the code of the example you are interested in. This tool will generate:

- a Go module for the example, including:
- go.mod and go.sum files, including the current version of _Testcontainer for Go_.
- a Go package named after the example, in lowercase
- a Go file for the creation of the container, using a dedicated struct in which the image flag is set as Docker image.
- a Go test file for running a simple test for your container, consuming the above struct.
- a Makefile to run the tests in a consistent manner
- a tools.go file including the build tools (i.e. `gotestsum`) used to build/run the example.
- a markdown file in the docs/examples directory including the snippets for both the creation of the container and a simple test.
- a new Nav entry for the example in the docs site, adding it to the `mkdocs.yml` file located at the root directory of the project.
- a GitHub workflow file in the .github/workflows directory to run the tests for the example.

### Command line flags

| Flag | Type | Required | Description |
|------|------|----------|-------------|
| -name | string | Yes | Name of the example, use camel-case when needed. Only alphabetical characters are allowed. |
| -image | string | Yes | Fully-qualified name of the Docker image to be used by the example (i.e. 'docker.io/org/project:tag') |
| -title | string | No | A variant of the name supporting mixed casing (i.e. 'MongoDB'). Only alphabetical characters are allowed. |

### What is this tool not doing?
Their main goal is to create shareable code snippets on how to use certain technology (e.g. a database, a web server), in order to explore its usage before converting the example module into a real Go module exposing a public API.

- If the example name does not contain alphabetical characters, it will exit the generation.
- If the example already exists, it will exit without updating the existing files.

### How to run the tool

From the [`examples` directory]({{repo_url}}/tree/main/examples), please run:
## Interested in adding a new example?

```shell
go run . --name ${NAME_OF_YOUR_EXAMPLE} --image "${REGISTRY}/${EXAMPLE}:${TAG}" --title ${TITLE_OF_YOUR_EXAMPLE}
```
Please refer to the documentation of the code generation tool [here](../modules/index.md).

## Update Go dependencies in the examples

Expand Down
56 changes: 56 additions & 0 deletions docs/modules/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Testcontainers for Go modules

In this section you'll discover how to create Go modules for _Testcontainers for Go_.

## Interested in adding a new module?

We have provided a command line tool to generate the scaffolding for the code of the example you are interested in. This tool will generate:

- a Go module for the example, including:
- go.mod and go.sum files, including the current version of _Testcontainer for Go_.
- a Go package named after the module, in lowercase
- a Go file for the creation of the container, using a dedicated struct in which the image flag is set as Docker image.
- a Go test file for running a simple test for your container, consuming the above struct.
- a Makefile to run the tests in a consistent manner
- a tools.go file including the build tools (i.e. `gotestsum`) used to build/run the example.
- a markdown file in the docs/modules directory including the snippets for both the creation of the container and a simple test.
- a new Nav entry for the module in the docs site, adding it to the `mkdocs.yml` file located at the root directory of the project.
- a GitHub workflow file in the .github/workflows directory to run the tests for the example.
- an entry in Dependabot's configuration file, in order to receive dependency updates.

### Command line flags

| Flag | Type | Required | Description |
|------|------|----------|-------------|
| -name | string | Yes | Name of the module, use camel-case when needed. Only alphabetical characters are allowed. |
| -image | string | Yes | Fully-qualified name of the Docker image to be used by the module (i.e. 'docker.io/org/project:tag') |
| -title | string | No | A variant of the name supporting mixed casing (i.e. 'MongoDB'). Only alphabetical characters are allowed. |
| -as-module | bool | No | If set, the module will be generated as a Go module, under the modules directory. Otherwise, it will be generated as a subdirectory of the examples directory. |

### What is this tool not doing?

- If the module name does not contain alphabetical characters, it will exit the generation.
- If the module already exists, it will exit without updating the existing files.

### How to run the tool

From the [`modulegen` directory]({{repo_url}}/tree/main/modulegen), please run:

```shell
go run . --name ${NAME_OF_YOUR_MODULE} --image "${REGISTRY}/${MODULE}:${TAG}" --title ${TITLE_OF_YOUR_MODULE}
```

or for creating a Go module:

```shell
go run . --name ${NAME_OF_YOUR_MODULE} --image "${REGISTRY}/${MODULE}:${TAG}" --title ${TITLE_OF_YOUR_MODULE} --as-module
```

## Update Go dependencies in the modules

To update the Go dependencies in the modules, please run:

```shell
$ cd modules
$ make tidy-examples
```
File renamed without changes.
7 changes: 0 additions & 7 deletions examples/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ include ../commons-test.mk
dependencies-scan-examples:
@find . -type f -name Makefile -execdir make dependencies-scan \;

.PHONY: test
test: test-unit
$(MAKE) -C cockroachdb test
$(MAKE) -C nginx test
$(MAKE) -C pulsar test
$(MAKE) -C redis test

.PHONY: tidy-examples
tidy-examples:
@find . -type f -name Makefile -execdir make tools-tidy \;
28 changes: 0 additions & 28 deletions examples/_template/example.go.tmpl

This file was deleted.

5 changes: 3 additions & 2 deletions examples/bigtable/bigtable.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package bigtable
import (
"context"
"fmt"

"github.com/testcontainers/testcontainers-go/wait"

"github.com/testcontainers/testcontainers-go"
Expand All @@ -14,8 +15,8 @@ type bigtableContainer struct {
URI string
}

// setupBigtable creates an instance of the bigtable container type
func setupBigtable(ctx context.Context) (*bigtableContainer, error) {
// startContainer creates an instance of the bigtable container type
func startContainer(ctx context.Context) (*bigtableContainer, error) {
req := testcontainers.ContainerRequest{
Image: "gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators",
ExposedPorts: []string{"9000/tcp"},
Expand Down
2 changes: 1 addition & 1 deletion examples/bigtable/bigtable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const (
func TestBigtable(t *testing.T) {
ctx := context.Background()

container, err := setupBigtable(ctx)
container, err := startContainer(ctx)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion examples/cockroachdb/cockroachdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type cockroachDBContainer struct {
URI string
}

func setupCockroachDB(ctx context.Context) (*cockroachDBContainer, error) {
func startContainer(ctx context.Context) (*cockroachDBContainer, error) {
req := testcontainers.ContainerRequest{
Image: "cockroachdb/cockroach:latest-v21.1",
ExposedPorts: []string{"26257/tcp", "8080/tcp"},
Expand Down
2 changes: 1 addition & 1 deletion examples/cockroachdb/cockroachdb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TestIntegrationDBInsertSelect(t *testing.T) {

ctx := context.Background()

cdbContainer, err := setupCockroachDB(ctx)
cdbContainer, err := startContainer(ctx)
if err != nil {
t.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions examples/consul/consul.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ type consulContainer struct {
endpoint string
}

// setupConsul creates an instance of the consul container type
func setupConsul(ctx context.Context) (*consulContainer, error) {
// startContainer creates an instance of the consul container type
func startContainer(ctx context.Context) (*consulContainer, error) {
req := testcontainers.ContainerRequest{
Image: "consul:latest",
ExposedPorts: []string{"8500/tcp", "8600/udp"},
Expand Down
2 changes: 1 addition & 1 deletion examples/consul/consul_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
func TestConsul(t *testing.T) {
ctx := context.Background()

container, err := setupConsul(ctx)
container, err := startContainer(ctx)
if err != nil {
t.Fatal(err)
}
Expand Down
5 changes: 3 additions & 2 deletions examples/datastore/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package datastore
import (
"context"
"fmt"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
Expand All @@ -13,8 +14,8 @@ type datastoreContainer struct {
URI string
}

// setupDatastore creates an instance of the datastore container type
func setupDatastore(ctx context.Context) (*datastoreContainer, error) {
// startContainer creates an instance of the datastore container type
func startContainer(ctx context.Context) (*datastoreContainer, error) {
req := testcontainers.ContainerRequest{
Image: "gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators",
ExposedPorts: []string{"8081/tcp"},
Expand Down
2 changes: 1 addition & 1 deletion examples/datastore/datastore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Task struct {
func TestDatastore(t *testing.T) {
ctx := context.Background()

container, err := setupDatastore(ctx)
container, err := startContainer(ctx)
if err != nil {
t.Fatal(err)
}
Expand Down
5 changes: 3 additions & 2 deletions examples/firestore/firestore.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package firestore
import (
"context"
"fmt"

"github.com/testcontainers/testcontainers-go/wait"

"github.com/testcontainers/testcontainers-go"
Expand All @@ -14,8 +15,8 @@ type firestoreContainer struct {
URI string
}

// setupFirestore creates an instance of the firestore container type
func setupFirestore(ctx context.Context) (*firestoreContainer, error) {
// startContainer creates an instance of the firestore container type
func startContainer(ctx context.Context) (*firestoreContainer, error) {
req := testcontainers.ContainerRequest{
Image: "gcr.io/google.com/cloudsdktool/cloud-sdk:367.0.0-emulators",
ExposedPorts: []string{"8080/tcp"},
Expand Down
2 changes: 1 addition & 1 deletion examples/firestore/firestore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (ec emulatorCreds) RequireTransportSecurity() bool {
func TestFirestore(t *testing.T) {
ctx := context.Background()

container, err := setupFirestore(ctx)
container, err := startContainer(ctx)
if err != nil {
t.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions examples/mongodb/mongodb.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ type mongodbContainer struct {
testcontainers.Container
}

// setupMongoDB creates an instance of the mongodb container type
func setupMongoDB(ctx context.Context) (*mongodbContainer, error) {
// startContainer creates an instance of the mongodb container type
func startContainer(ctx context.Context) (*mongodbContainer, error) {
req := testcontainers.ContainerRequest{
Image: "mongo:6",
ExposedPorts: []string{"27017/tcp"},
Expand Down
2 changes: 1 addition & 1 deletion examples/mongodb/mongodb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
func TestMongoDB(t *testing.T) {
ctx := context.Background()

container, err := setupMongoDB(ctx)
container, err := startContainer(ctx)
if err != nil {
t.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions examples/mysql/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ type mysqlContainer struct {
testcontainers.Container
}

// setupMysql creates an instance of the mysql container type
func setupMysql(ctx context.Context) (*mysqlContainer, error) {
// startContainer creates an instance of the mysql container type
func startContainer(ctx context.Context) (*mysqlContainer, error) {
req := testcontainers.ContainerRequest{
Image: "mysql:8",
ExposedPorts: []string{"3306/tcp", "33060/tcp"},
Expand Down
2 changes: 1 addition & 1 deletion examples/mysql/mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
func TestMysql(t *testing.T) {
ctx := context.Background()

container, err := setupMysql(ctx)
container, err := startContainer(ctx)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion examples/nginx/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type nginxContainer struct {
URI string
}

func setupNginx(ctx context.Context) (*nginxContainer, error) {
func startContainer(ctx context.Context) (*nginxContainer, error) {
req := testcontainers.ContainerRequest{
Image: "nginx",
ExposedPorts: []string{"80/tcp"},
Expand Down
2 changes: 1 addition & 1 deletion examples/nginx/nginx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestIntegrationNginxLatestReturn(t *testing.T) {

ctx := context.Background()

nginxC, err := setupNginx(ctx)
nginxC, err := startContainer(ctx)
if err != nil {
t.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions examples/postgres/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ func WithInitialDatabase(user string, password string, dbName string) func(req *
}
}

// setupPostgres creates an instance of the postgres container type
func setupPostgres(ctx context.Context, opts ...postgresContainerOption) (*postgresContainer, error) {
// startContainer creates an instance of the postgres container type
func startContainer(ctx context.Context, opts ...postgresContainerOption) (*postgresContainer, error) {
req := testcontainers.ContainerRequest{
Image: "postgres:11-alpine",
Env: map[string]string{},
Expand Down
8 changes: 4 additions & 4 deletions examples/postgres/postgres_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func TestPostgres(t *testing.T) {
port, err := nat.NewPort("tcp", "5432")
require.NoError(t, err)

container, err := setupPostgres(ctx,
container, err := startContainer(ctx,
WithPort(port.Port()),
WithInitialDatabase(user, password, dbname),
WithWaitStrategy(wait.ForLog("database system is ready to accept connections").WithOccurrence(2).WithStartupTimeout(5*time.Second)),
Expand Down Expand Up @@ -77,12 +77,12 @@ func TestContainerWithWaitForSQL(t *testing.T) {
}

t.Run("default query", func(t *testing.T) {
container, err := setupPostgres(ctx, WithPort(port), WithInitialDatabase("postgres", "password", dbname), WithWaitStrategy(wait.ForSQL(nat.Port(port), "postgres", dbURL)))
container, err := startContainer(ctx, WithPort(port), WithInitialDatabase("postgres", "password", dbname), WithWaitStrategy(wait.ForSQL(nat.Port(port), "postgres", dbURL)))
require.NoError(t, err)
require.NotNil(t, container)
})
t.Run("custom query", func(t *testing.T) {
container, err := setupPostgres(
container, err := startContainer(
ctx,
WithPort(port),
WithInitialDatabase(user, password, dbname),
Expand All @@ -92,7 +92,7 @@ func TestContainerWithWaitForSQL(t *testing.T) {
require.NotNil(t, container)
})
t.Run("custom bad query", func(t *testing.T) {
container, err := setupPostgres(
container, err := startContainer(
ctx,
WithPort(port),
WithInitialDatabase(user, password, dbname),
Expand Down
Loading