Skip to content

Conversation

@MitulShah1
Copy link
Contributor

@MitulShah1 MitulShah1 commented May 2, 2025

#3124

What does this PR do?

Why is it important?

Related issues

@mdelapenya Can you please review

@MitulShah1 MitulShah1 requested a review from a team as a code owner May 2, 2025 09:36
@netlify
Copy link

netlify bot commented May 2, 2025

Deploy Preview for testcontainers-go ready!

Name Link
🔨 Latest commit 86f661b
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-go/deploys/68edcff1edf97b0008b40ae1
😎 Deploy Preview https://deploy-preview-3151--testcontainers-go.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@MitulShah1 MitulShah1 changed the title Add ssl option cassandra feat(cassandra): Add ssl option cassandra May 2, 2025
@mdelapenya mdelapenya changed the title feat(cassandra): Add ssl option cassandra feat(cassandra): add ssl option cassandra May 3, 2025
Copy link
Member

@mdelapenya mdelapenya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, although I added some comments about using the same approach as in the Redis module. Could you please take a look?

Cheers!

),
}

c := &CassandraContainer{}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: keep this initialisation next to its usage. Seems moved here for no reasons

data, _ := io.ReadAll(body)
return strings.Contains(string(data), "COMPLETED")
}),
}).WithStartupTimeout(2*time.Minute),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: is 2 minutes too long? Can we use a shorter duration?

Comment on lines 160 to 161
"CASSANDRA_SKIP_WAIT_FOR_GOSSIP": "1",
"CASSANDRA_START_NATIVE_TRANSPORT": "true",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: are these new env vars related to the SSL options? If not, I'd separate the changes into a new PR, if possible

}

// WithTLS is an alias for WithSSL for user convenience
func WithTLS(opts SSLOptions) testcontainers.CustomizeRequestOption {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: why adding two flavours of the same option? I'd just choose one to avoid creating confusion on users

}

// Mark that SSL is enabled for later use
req.Labels = mergeMap(req.Labels, map[string]string{"testcontainers.cassandra.ssl": "true"})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: I guess this is needed to notify the Run function about the SSL addition, right? I'd choose a different pattern for this, creating an options type as in the redis module. Then, you can simply generate the SSL certs on-the-fly as in that module.

@MitulShah1 MitulShah1 requested a review from mdelapenya May 7, 2025 07:05
@MitulShah1
Copy link
Contributor Author

Looking good, although I added some comments about using the same approach as in the Redis module. Could you please take a look?

Cheers!

I made changes, can you please check again?

Copy link
Contributor

@stevenh stevenh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the quick updates, here's some suggestion which focus on simplification and reducing API surface area.

Comment on lines 15 to 16
IsTLSEnabled bool
TLSConfig *tls.Config
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: make these private so there's less API surface area allowing for refactoring without causing breaking changes. Given it's typed nature we can skip the Is prefix for boolean flag too.

Suggested change
IsTLSEnabled bool
TLSConfig *tls.Config
tlsEnabled bool
tlsConfig *tls.Config

More fixes to align with this change obviously, so best to just rename in your editor.

Comment on lines +44 to +45
// GenerateJKSKeystore generates a JKS keystore with a self-signed cert using keytool, and extracts the public cert for Go client trust.
func GenerateJKSKeystore() (keystorePath, certPath string, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: make private, again less API surface area to maintain. Also needs to use go not an external tool which might not be present on all platforms. See other modules on how they generate keys, hopefully that's compatible with cassandra.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stevenh making this function private, i need to change in options_test.go, its ok?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either that or make a seperate test file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options_test.go is created by me only but i cannot access that function as testcases are depend on it, do you want me to make this function private and remove options_test.go?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Up to you, having integration and unit tests are both good. In go its not a problem to use the main package for tests, as long as you're conscious about the seperation.

However can we should first see if we can eliminate this external dependency. You can see a similar example here: https://github.com/testcontainers/testcontainers-go/blob/main/modules/redis/options.go#L86 which uses https://pkg.go.dev/github.com/mdelapenya/tlscert

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems you're suggesting we either minimize SSL-related dependencies or simply support SSL with minimal setup. I always try to follow the existing repository codebase and coding style as much possible.

Initially, I tried using only tlscert, but it has some limitations. If we choose to use tlscert, we can eliminate the keytool dependency, but we'd then need to rely on openssl.

So, we have two options:

Use keytool as we currently do.

Follow an approach similar to Cassandra's Go driver, where certificates are added in a testdata folder and used for SSL testing, as seen in the official Go driver.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tlscert would be the preferred option as it's what a lot of the other modules use.

If it needs changes that should be quick and easy as that module is written by @mdelapenya one of this repositories maintainers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know but it can handle this cassandra cert generation? @mdelapenya ? i already tried that let me know if ok to use openssl then i will make change to tlscert.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's use it for consistency. If there is a missing feature in that library, let's open an issue in there and work on fix and release it

Cheers!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A Quick Look and it seems like it can use standard pen formatted certs so it should just work

@MitulShah1 MitulShah1 requested a review from stevenh May 7, 2025 10:36
Copy link
Contributor

@stevenh stevenh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few bugs introduced here I think, the big question is eliminating the use of external dependency keytool

Comment on lines +44 to +45
// GenerateJKSKeystore generates a JKS keystore with a self-signed cert using keytool, and extracts the public cert for Go client trust.
func GenerateJKSKeystore() (keystorePath, certPath string, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Up to you, having integration and unit tests are both good. In go its not a problem to use the main package for tests, as long as you're conscious about the seperation.

However can we should first see if we can eliminate this external dependency. You can see a similar example here: https://github.com/testcontainers/testcontainers-go/blob/main/modules/redis/options.go#L86 which uses https://pkg.go.dev/github.com/mdelapenya/tlscert

const (
port = nat.Port("9042/tcp")
port = nat.Port("9042/tcp")
securePort = nat.Port("9142/tcp") // Common port for SSL/TLS connections
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: do we need to two ports or can it just be one which is either SSL or not?

Comment on lines +118 to +124
waitStrategies := []wait.Strategy{
wait.ForListeningPort(port),
wait.ForExec([]string{"cqlsh", "-e", "SELECT bootstrapped FROM system.local"}).WithResponseMatcher(func(body io.Reader) bool {
data, _ := io.ReadAll(body)
return strings.Contains(string(data), "COMPLETED")
}).WithStartupTimeout(1 * time.Minute),
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mdelapenya looks like we have an issue with WithWaitStrategy, it sets vs appending to WaitFor preventing easy initialisation here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. I think the use case here would be appending. I can submit a fix now


// Apply wait strategy using the correct method
if err := testcontainers.WithWaitStrategy(wait.ForAll(waitStrategies...)).Customize(&genericContainerReq); err != nil {
return nil, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: wrap the error here

Suggested change
return nil, err
return nil, fmt.Errorf("with wait strategy: %w", err)

Comment on lines +149 to +150
// TLSConfig returns the TLS configuration for the Cassandra container, nil if TLS is not enabled.
func (c *CassandraContainer) TLSConfig() *tls.Config {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mdelapenya quite a common pattern in modules, we should consider returning an error instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean the pointer to the config and the error, right? I think we changed the tlscert library precisely for that, so good to me to change it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, these container methods, have them return an error if the config is nil vs just returning nil as the caller should know if they enabled TLS or not.

func (c *CassandraContainer) TLSConfig() (*tls.Config, error) {
	if c.settings.tlsConfig == nil {
		return nil, errors.New("tls not enabled")
	}
	return c.settings.tlsConfig.Config, nil
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see, the recently added methods for Redis and Valkey. For Valkey, we are in the same release cycle, we can change it without BC, for Redis, it's a BC

Comment on lines +31 to +32
func (o Option) Customize(req *testcontainers.GenericContainerRequest) error {
return o(req, &Options{})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug: while this will run there options won't be accessible, so should still be just a noop.

We're looking to refactor how this works in a future version to avoid this, but that will be a bit.

Started: true,
}

var settings Options
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bug: settings is never set, you still need to check if you have an Option in the for loop and process it to ensure it set correctly.

If your tests are passing they shouldn't so might need a fix there too.

Comment on lines +15 to +16
// TLSConfig represents the TLS configuration for Cassandra
type TLSConfig struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: are the paths needed? If not we can just return *tls.Config. I suspect the answer is dependent on eliminating the need for keytool

@mdelapenya
Copy link
Member

@MitulShah1 did you have the chance to take a look a the comments here?

@MitulShah1
Copy link
Contributor Author

@MitulShah1 did you have the chance to take a look a the comments here?

Sorry lil busy, i will check and try to finish this week.

@gaby
Copy link

gaby commented Oct 13, 2025

@mdelapenya @MitulShah1 any progress on this?

@MitulShah1
Copy link
Contributor Author

@mdelapenya @MitulShah1 any progress on this?

Hey @gaby @mdelapenya sorry for delay but i tried with simple tlc certy which @stevenh mentioned with @mdelapenya library seems its not working with cassandra. so just stuck on this point only.

# Conflicts:
#	modules/cassandra/cassandra.go
@coderabbitai
Copy link

coderabbitai bot commented Oct 14, 2025

Summary by CodeRabbit

  • New Features
    • Added optional SSL/TLS support for Cassandra containers, including secure client port exposure (9142) and automatic keystore/certificate generation.
    • Exposed a public way to retrieve TLS configuration for client connections.
    • Introduced configurable options to enable SSL and customize container behavior.
  • Documentation
    • Added an SSL example showing how to start Cassandra with TLS and connect using a secure client.
  • Tests
    • Added SSL integration test validating secure connectivity.
    • Added tests covering keystore generation, overwriting behavior, and error handling.

Walkthrough

Adds TLS/SSL support and option-driven configuration to the Cassandra testcontainer module, including secure port exposure, TLS-aware connection host selection, keystore/cert generation, TLS wait strategies, and a public TLSConfig accessor. Updates tests and examples to cover SSL flows and introduces a Cassandra SSL YAML test config.

Changes

Cohort / File(s) Summary
Core TLS integration and container orchestration
modules/cassandra/cassandra.go
Adds TLS-aware ports (9042, 9142), selects connection port based on TLS, introduces Options storage, refactors Run to build GenericContainerRequest, applies wait strategies (default, CQLSH, conditional TLS), exposes TLSConfig() method.
Option system and TLS assets
modules/cassandra/options.go
Introduces Option/Options types, TLSConfig struct, WithSSL functional option, JKS keystore and cert generation (keytool), secure port exposure, file mounts, root CA pool creation, and retrieval of TLSConfig via Options.
Integration tests (Cassandra)
modules/cassandra/cassandra_test.go
Centralizes image constant; adds TestCassandraSSL using WithSSL and TLSConfig to connect via gocql and verify system.local; updates existing starts to use the constant.
Option tests (TLS/keystore)
modules/cassandra/options_test.go
Tests WithSSL effects (ports/files/TLS), keystore/cert generation, overwrite behavior, and failure when keytool is unavailable.
Examples
modules/cassandra/examples_test.go
Adds ExampleRun_withSSL showing starting Cassandra with SSL, obtaining TLS config, connecting with gocql, and querying release_version.
Test data (SSL config)
modules/cassandra/testdata/cassandra-ssl.yaml
Adds Cassandra SSL configuration YAML with client_encryption_options, keystore paths, and native_transport_port_ssl.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Caller
  participant CassandraContainer
  participant Options
  participant Keytool
  participant Testcontainers as Testcontainers-Go
  participant Cassandra as Cassandra (container)
  participant Client as gocql Client

  Caller->>CassandraContainer: Run(ctx, req, WithSSL(), WithConfigFile(...))
  CassandraContainer->>Options: Apply WithSSL
  Options->>Keytool: GenerateJKSKeystore()
  Keytool-->>Options: keystore.jks, cert.pem
  Options-->>CassandraContainer: TLSConfig, secure port (9142), files
  CassandraContainer->>Testcontainers: GenericContainerRequest (ExposedPorts 9042,9142 + waits)
  Testcontainers->>Cassandra: Start container
  Cassandra-->>Testcontainers: Service up
  Testcontainers-->>CassandraContainer: Container handle

  note over CassandraContainer,Client: TLS-enabled flow
  Caller->>CassandraContainer: TLSConfig()
  CassandraContainer-->>Caller: *tls.Config (or nil)
  Caller->>Client: Create cluster with SslOptions/TLSConfig and host:9142
  Client->>Cassandra: Connect, query system.local
  Cassandra-->>Client: release_version
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I brewed a keystore under moonlit logs,
Two ports now sing—secure among the cogs.
With whiskers twitching, I trust the cert,
Hop to 9142, no plaintext hurt.
CQL hums softly, tests all pass—
A rabbit toasts SSL in glass. 🐇🔐

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description Check ❓ Inconclusive The description consists solely of placeholder headings without any substantive details about what changes were made, why they were necessary, or how to test them, leaving readers without meaningful context. Please update the description to summarize the implemented features, explain the motivation for adding SSL support, and include instructions for testing the new functionality.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title clearly reflects the primary change by indicating the addition of an SSL option for the Cassandra module and follows the conventional “feat(scope): description” format, making the main feature obvious to readers. Although it repeats “cassandra,” it remains concise and specific to the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (3)
modules/cassandra/options.go (3)

15-20: Make TLSConfig fields private to reduce API surface area.

The public fields increase the API surface area and make future refactoring difficult. Since these fields are accessed through the TLSConfig() method, they should be private.

Based on past review feedback, if the tlscert library is adopted (as requested), the paths may not be needed at all—only the *tls.Config would be necessary.

Apply this diff to make the fields private:

 // TLSConfig represents the TLS configuration for Cassandra
 type TLSConfig struct {
-	KeystorePath    string
-	CertificatePath string
-	Config          *tls.Config
+	keystorePath    string
+	certificatePath string
+	config          *tls.Config
 }

Then update the accessor method and any references accordingly.


31-33: Critical bug: Options are discarded on every call.

Line 32 creates a fresh Options{} instead of accumulating settings across multiple option calls. This means any TLS configuration set by WithSSL() will be lost, and the container won't have access to the TLS settings.

This exact issue was flagged in previous reviews: "while this will run there options won't be accessible."

The current implementation should be treated as a no-op until the broader options refactoring is completed. However, to make it functional in the interim, the accumulated settings need to be passed through. The WithSSL function should directly modify the GenericContainerRequest without relying on the Options struct being carried forward by Customize.

One interim approach is to store the accumulated options outside the Customize call chain, but this requires broader changes to how Run accesses the settings. See modules/cassandra/cassandra.go lines 79-135 for how settings are currently extracted.


81-122: Make function private and plan for removal.

This function was requested to be made private in previous reviews to reduce API surface area. More importantly, it should be removed entirely once the tlscert library is adopted (see comment on lines 35-79).

The reliance on external keytool creates several issues:

  • Not available on all platforms (requires Java/JDK installation)
  • Harder to maintain and test
  • Inconsistent with other testcontainers-go modules

If keeping this temporarily during the transition:

-// GenerateJKSKeystore generates a JKS keystore with a self-signed cert using keytool, and extracts the public cert for Go client trust.
-func GenerateJKSKeystore() (keystorePath, certPath string, err error) {
+// generateJKSKeystore generates a JKS keystore with a self-signed cert using keytool, and extracts the public cert for Go client trust.
+// Deprecated: Will be removed once tlscert-based implementation is complete.
+func generateJKSKeystore() (keystorePath, certPath string, err error) {

Then update the call in WithSSL (line 40) accordingly. However, prioritize replacing this entirely with the tlscert approach.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ae0c648 and 86f661b.

📒 Files selected for processing (6)
  • modules/cassandra/cassandra.go (3 hunks)
  • modules/cassandra/cassandra_test.go (7 hunks)
  • modules/cassandra/examples_test.go (2 hunks)
  • modules/cassandra/options.go (1 hunks)
  • modules/cassandra/options_test.go (1 hunks)
  • modules/cassandra/testdata/cassandra-ssl.yaml (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
modules/cassandra/examples_test.go (4)
modules/cassandra/cassandra.go (2)
  • Run (80-136)
  • WithConfigFile (42-52)
modules/cassandra/options.go (2)
  • WithSSL (36-79)
  • TLSConfig (16-20)
cleanup.go (1)
  • TerminateContainer (97-108)
log/logger.go (1)
  • Printf (47-49)
modules/cassandra/options.go (3)
generic.go (1)
  • GenericContainerRequest (21-27)
container.go (1)
  • ContainerFile (110-115)
modules/cassandra/cassandra.go (1)
  • Run (80-136)
modules/cassandra/cassandra_test.go (3)
modules/cassandra/cassandra.go (3)
  • Run (80-136)
  • WithConfigFile (42-52)
  • WithInitScripts (55-71)
modules/cassandra/options.go (2)
  • WithSSL (36-79)
  • TLSConfig (16-20)
testing.go (1)
  • CleanupContainer (91-97)
modules/cassandra/cassandra.go (7)
modules/cassandra/options.go (2)
  • Options (23-25)
  • TLSConfig (16-20)
container.go (1)
  • ContainerRequest (131-171)
generic.go (2)
  • GenericContainerRequest (21-27)
  • GenericContainer (52-98)
wait/host_port.go (1)
  • ForListeningPort (67-69)
wait/exec.go (1)
  • ForExec (71-73)
options.go (1)
  • WithWaitStrategy (366-368)
wait/all.go (1)
  • ForAll (44-48)
modules/cassandra/options_test.go (3)
generic.go (1)
  • GenericContainerRequest (21-27)
container.go (1)
  • ContainerRequest (131-171)
modules/cassandra/options.go (4)
  • Options (23-25)
  • WithSSL (36-79)
  • TLSConfig (16-20)
  • GenerateJKSKeystore (82-122)
🪛 GitHub Actions: Main pipeline
modules/cassandra/cassandra.go

[error] 17-17: undefined: nat

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (1)
modules/cassandra/options.go (1)

35-79: Cannot confirm PEM-based TLS support in test data
I didn’t find any store_type: PEM entries in modules/cassandra/testdata. Please verify that your Cassandra version (4.0+) and testdata configuration support PEM-based TLS or update the testdata accordingly.

Comment on lines 3 to 14
import (
"context"
"crypto/tls"
"fmt"
"io"
"path/filepath"
"strings"
"time"

"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add the nat import to fix compilation.

nat.Port is used for port/securePort, but github.com/docker/go-connections/nat is not imported, so the branch fails to build (undefined: nat in the pipeline). Please add the missing import:

 import (
 	"context"
 	"crypto/tls"
 	"fmt"
 	"io"
 	"path/filepath"
 	"strings"
 	"time"

+	"github.com/docker/go-connections/nat"
 	"github.com/testcontainers/testcontainers-go"
 	"github.com/testcontainers/testcontainers-go/wait"
 )

Based on pipeline failure logs.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import (
"context"
"crypto/tls"
"fmt"
"io"
"path/filepath"
"strings"
"time"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
import (
"context"
"crypto/tls"
"fmt"
"io"
"path/filepath"
"strings"
"time"
"github.com/docker/go-connections/nat"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
🤖 Prompt for AI Agents
In modules/cassandra/cassandra.go around lines 3 to 14, the code uses nat.Port
for port/securePort but does not import github.com/docker/go-connections/nat,
causing a compile error (undefined: nat); fix by adding the missing import
("github.com/docker/go-connections/nat") to the import block (keep the import
alias as nat if needed) so nat.Port is available to the file.

Comment on lines +66 to +74
require.Equal(t, keystorePath, newKeystorePath)
require.Equal(t, certPath, newCertPath)

// Get new file info
newKeystoreInfo, err := os.Stat(keystorePath)
require.NoError(t, err)

// Verify that the file was modified
require.NotEqual(t, initialKeystoreInfo.ModTime(), newKeystoreInfo.ModTime(), "keystore should be overwritten")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Avoid shared keystore paths across invocations.

GenerateJKSKeystore always returns /tmp/keystore.jks and cert.pem. When two Cassandra containers enable SSL at the same time, the second call removes and regenerates those files while the first container still holds the original certificate in its TLS config. The container then ships with the new cert while the client still trusts the old one, so the TLS handshake breaks. Please generate unique temp files per invocation (for example via os.CreateTemp) and update the tests to expect distinct paths so concurrent runs stay correct.

🤖 Prompt for AI Agents
In modules/cassandra/options_test.go around lines 66 to 74, the test and
implementation rely on fixed paths (/tmp/keystore.jks and cert.pem) causing race
conditions when multiple invocations overwrite the same files; change
GenerateJKSKeystore to create unique temporary files (e.g., use os.CreateTemp or
os.MkdirTemp + unique filenames) for both the keystore and cert, return those
paths, and ensure the function still writes the keystore/cert and cleans up
where appropriate; update the test to assert that the returned keystore and cert
paths are distinct from one another and from any previous run (use the returned
paths to stat the files and compare mod times) instead of assuming fixed /tmp
paths so concurrent runs do not clobber each other.

@mdelapenya
Copy link
Member

@gaby @MitulShah1 thanks for the ping. I'll resolve the conflicts locally and will try to check the TLS issues mentioned above.

@MitulShah1 can you elaborate on those issues with tlscert?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants