Skip to content

Commit

Permalink
feat(nats): WithConfigFile - pass a configuration file to nats server (
Browse files Browse the repository at this point in the history
…#2905)

* feat: WithConfigFile - pass a configuration file to nats server

* add a testcase with a incorrect token

* use testcontainers.ContainerCustomizer as suggested during CR

Add ConfigGile struct, which implements the interface.

* drop a custom struct, return and implement an interface directly

* docs: document nats.WithConfigFile

* Update modules/nats/options.go

Co-authored-by: Manuel de la Peña <[email protected]>

* Update docs/modules/nats.md

Co-authored-by: Manuel de la Peña <[email protected]>

* Update docs/modules/nats.md

Co-authored-by: Manuel de la Peña <[email protected]>

* remove document markers from a unit test

* address CR comments

* fix a comment

---------

Co-authored-by: Manuel de la Peña <[email protected]>
  • Loading branch information
vyskocilm and mdelapenya authored Dec 5, 2024
1 parent 512e503 commit 0bbab5e
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 2 deletions.
11 changes: 10 additions & 1 deletion docs/modules/nats.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ These arguments are passed to the NATS server when it starts, as part of the com
[Passing arguments](../../modules/nats/examples_test.go) inside_block:withArguments
<!--/codeinclude-->
#### Custom configuration file
- Not available until the next release of testcontainers-go <a href="https://github.com/testcontainers/testcontainers-go"><span class="tc-version">:material-tag: main</span></a>
It's possible to pass a custom config file to NATS container using `nats.WithConfigFile(strings.NewReader(config))`. The content of `io.Reader` is passed as a `-config /etc/nats.conf` arguments to an entrypoint.

!!! note
Changing the connectivity (listen address or ports) can break the container setup. So configuration must be done with care.

### Container Methods

The NATS container exposes the following methods:
Expand Down Expand Up @@ -102,4 +111,4 @@ Exactly like `ConnectionString`, but it panics if an error occurs, returning jus
<!--codeinclude-->
[NATS Cluster](../../modules/nats/examples_test.go) inside_block:cluster
<!--/codeinclude-->
<!--/codeinclude-->
47 changes: 47 additions & 0 deletions modules/nats/nats_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package nats_test

import (
"bufio"
"context"
"strings"
"testing"
"time"

"github.com/nats-io/nats.go"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -57,3 +60,47 @@ func TestNATS(t *testing.T) {

require.Equal(t, "hello", string(msg.Data))
}

func TestNATSWithConfigFile(t *testing.T) {
const natsConf = `
listen: 0.0.0.0:4222
authorization {
token: "s3cr3t"
}
`
ctx := context.Background()

ctr, err := tcnats.Run(ctx, "nats:2.9", tcnats.WithConfigFile(strings.NewReader(natsConf)))
testcontainers.CleanupContainer(t, ctr)
require.NoError(t, err)

uri, err := ctr.ConnectionString(ctx)
require.NoError(t, err)

// connect without a correct token must fail
mallory, err := nats.Connect(uri, nats.Name("Mallory"), nats.Token("secret"))
t.Cleanup(mallory.Close)
require.EqualError(t, err, "nats: Authorization Violation")

// connect with a correct token must succeed
nc, err := nats.Connect(uri, nats.Name("API Token Test"), nats.Token("s3cr3t"))
t.Cleanup(nc.Close)
require.NoError(t, err)

// validate /etc/nats.conf mentioned in logs
const expected = "Using configuration file: /etc/nats.conf"
logs, err := ctr.Logs(ctx)
require.NoError(t, err)
sc := bufio.NewScanner(logs)
found := false
time.AfterFunc(5*time.Second, func() {
require.Truef(t, found, "expected log line not found after 5 seconds: %s", expected)
})
for sc.Scan() {
if strings.Contains(sc.Text(), expected) {
found = true
break
}
}
require.Truef(t, found, "expected log line not found: %s", expected)
}
22 changes: 21 additions & 1 deletion modules/nats/options.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package nats

import (
"io"
"strings"

"github.com/testcontainers/testcontainers-go"
Expand All @@ -16,7 +17,7 @@ func defaultOptions() options {
}
}

// Compiler check to ensure that Option implements the testcontainers.ContainerCustomizer interface.
// Compiler check to ensure that CmdOption implements the testcontainers.ContainerCustomizer interface.
var _ testcontainers.ContainerCustomizer = (*CmdOption)(nil)

// CmdOption is an option for the NATS container.
Expand Down Expand Up @@ -49,3 +50,22 @@ func WithArgument(flag string, value string) CmdOption {
o.CmdArgs[flag] = value
}
}

// WithConfigFile pass a content of io.Reader to the NATS container as /etc/nats.conf
// Changing the connectivity (listen address or ports) can break the container setup.
func WithConfigFile(config io.Reader) testcontainers.CustomizeRequestOption {
return func(req *testcontainers.GenericContainerRequest) error {
if config != nil {
req.Cmd = append(req.Cmd, "-config", "/etc/nats.conf")
req.Files = append(
req.Files,
testcontainers.ContainerFile{
Reader: config,
ContainerFilePath: "/etc/nats.conf",
FileMode: 0o644,
},
)
}
return nil
}
}

0 comments on commit 0bbab5e

Please sign in to comment.