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 50579f9
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-go/deploys/6936673d646d17000829183d
😎 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!

@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.

@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

Warning

Rate limit exceeded

@MitulShah1 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 6 minutes and 57 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 178c16f and 50579f9.

📒 Files selected for processing (4)
  • docs/modules/cassandra.md (1 hunks)
  • modules/cassandra/cassandra.go (4 hunks)
  • modules/cassandra/cassandra_test.go (1 hunks)
  • modules/cassandra/examples_test.go (1 hunks)

Summary by CodeRabbit

  • New Features

    • Added TLS/SSL support for Cassandra containers with automatic self-signed certificate generation
    • Added WithTLS() option to enable secure connections
    • Added TLSConfig() method to retrieve TLS configuration
    • SSL port 9142 automatically exposed when TLS is enabled
  • Tests

    • Added TLS integration test with complete data operations
    • Added TLS usage example
  • Documentation

    • Added TLS configuration guide with code examples

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Adds optional TLS support for Cassandra containers: generates CA/server certificates and a PKCS#12 keystore, exposes SSL port 9142, introduces WithTLS() option and TLSConfig() accessor, mounts SSL config and keystore into the container, and adds tests/examples demonstrating TLS client connections.

Changes

Cohort / File(s) Summary
Core Cassandra TLS Integration
modules/cassandra/cassandra.go
Adds TLS awareness (sslPort 9142), embeds SSL YAML, adds settings options field, switches ConnectionHost to use SSL port when enabled, adds TLSConfig() method, updates Run to generate certs, mount SSL files, adjust env/networking, expose SSL port, and extend wait strategy.
TLS Materials & Creation
modules/cassandra/tls.go
Implements internal tlsCerts and createTLSCerts() to generate a CA, server certificate, PKCS#12 keystore (password "cassandra"), and a prepared tls.Config with CA pool and ServerName "localhost".
Options Pattern / Public API
modules/cassandra/options.go
Adds Option type and WithTLS() option; Option implements testcontainers.ContainerCustomizer via Customize, plus default options initializer to carry runtime tlsEnabled state.
Cassandra SSL Configuration
modules/cassandra/testdata/cassandra-ssl.yaml
Adds a Cassandra configuration YAML enabling client encryption, native_transport_port_ssl, keystore references, and related SSL/security settings used when TLS is enabled.
Tests & Examples
modules/cassandra/cassandra_test.go, modules/cassandra/examples_test.go
Adds TestCassandraWithTLS and ExampleRun_withTLS to validate and demonstrate TLS-configured container end-to-end (TLSConfig non-nil, TLS session, keyspace/table ops, and TLS-enabled gocql client).
Dependencies
modules/cassandra/go.mod
Adds github.com/mdelapenya/tlscert v0.2.0 and software.sslmate.com/src/go-pkcs12 v0.6.0 for certificate generation and PKCS#12 keystore encoding.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant Test as Test / Client
    participant Runner as CassandraContainer.Run
    participant TLSGen as createTLSCerts()
    participant Container as Testcontainers GenericContainer
    participant Cassandra as Cassandra process
    participant ClientLib as gocql (TLS client)

    Test->>Runner: Run(..., WithTLS())
    Runner->>TLSGen: generate CA, server cert, PKCS#12 keystore
    TLSGen-->>Runner: tlsCerts (keystore bytes, tls.Config)
    Runner->>Container: Start with mounted keystore & cassandra-ssl.yaml, expose 9142
    Container->>Cassandra: Cassandra starts using client_encryption_options (keystore)
    Runner->>Runner: store settings.TLSConfig
    Test->>ClientLib: build cluster using TLSConfig()
    ClientLib->>Cassandra: Establish TLS connection on 9142
    Cassandra-->>ClientLib: TLS handshake + query responses
    ClientLib-->>Test: Query results
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay attention to modules/cassandra/tls.go for certificate generation parameters, CA trust handling, and PKCS#12 encoding.
  • Review options.go integration and the Customize implementation with testcontainers request shaping.
  • Inspect cassandra.go changes: env var adjustments, file mounts, exposed ports, wait strategy extension, and storage/exposure of TLSConfig.
  • Run new tests/examples to validate end-to-end TLS behavior.

Poem

🐇 I hopped in with a tiny CA and key,

I wrapped a keystore snug for localhost to see.
Port nine-one-four-two now hums secure and bright,
Cassandra greets clients under encrypted light.

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 references issue #3124 and mentions SSL option addition but lacks implementation details and concrete explanation of changes. Provide details about what changes were made, why SSL support is important, and how reviewers can test the implementation.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main feature: adding SSL/TLS support to the Cassandra module via a new option.

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.

@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?

# Conflicts:
#	modules/cassandra/cassandra.go
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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
modules/cassandra/cassandra.go (1)

80-107: Run has multiple compile-time and logic issues (invalid literal, unused vars, wrong identifiers)

This block currently won’t compile and also doesn’t appear to use the new ContainerRequest:

  • req := testcontainers.ContainerRequest{ ... }:
    • The struct literal is syntactically invalid: Env: map[string]string{...}), testcontainers.WithWaitStrategy(...), leaves an extra ) after the map literal and introduces testcontainers.WithWaitStrategy(...) as a bare value in the struct, which is not keyed to any field. This matches the golangci-lint “unexpected ) in composite literal” error.
    • req is never used, so even once syntax is fixed you’ll get req declared and not used.
  • ctr, err := testcontainers.Run(ctx, img, moduleOpts...):
    • ctr is never used; later you reference container instead, which is undefined in this function.
  • In the next lines:
    • if container != nil { c = &CassandraContainer{Container: container, settings: settings} }
      • container isn’t declared in this scope; you probably meant ctr.
      • settings must come from the Options processing path; make sure it’s in scope here and set accordingly.

You’ll need to decide whether Run should:

  1. Use testcontainers.Run(ctx, img, ...) with ContainerCustomizers that set env and wait strategy (in which case you should remove the unused req entirely), or
  2. Build and pass a ContainerRequest through the lower-level API (GenericContainerRequest), in which case testcontainers.Run’s signature might not be the right call.

At minimum, to fix the immediate issues:

  • Make the struct literal valid or remove req if not used.
  • Replace container with ctr (and actually use ctr), and ensure settings is in scope and populated.
  • Confirm moduleOpts is defined in this package and includes any TLS/SSL customizers you intend.

Until these are addressed, this function will not compile.

♻️ Duplicate comments (2)
modules/cassandra/cassandra.go (2)

115-121: Consider returning (*tls.Config, error) from TLSConfig instead of a bare pointer

The new TLSConfig() accessor returns nil when TLS is not enabled. That works, but callers then have to remember to check for nil vs. treat it as a hard error.

Given prior discussion on similar methods in Redis/Valkey, it would be more explicit to return an error when TLS isn’t enabled, e.g.:

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
}

This makes misuse easier to detect and keeps patterns consistent across modules.

Check the current Redis and Valkey modules in testcontainers-go to confirm the preferred TLSConfig API shape (returning (*tls.Config, error) vs *tls.Config).

3-19: Missing nat import breaks the new port constants

port and securePort are declared as nat.Port("9042/tcp") / "9142/tcp", but github.com/docker/go-connections/nat is not imported. This file will not compile (undefined: nat).

Add the missing import to the import block:

 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"
 )
🧹 Nitpick comments (1)
modules/cassandra/cassandra.go (1)

21-37: Ensure settings is correctly initialised before using it in ConnectionHost

The new TLS-aware ConnectionHost picks securePort when c.settings.tlsConfig != nil, otherwise falls back to the plain port. That logic is fine, but it assumes:

  • c.settings is always initialised with the effective Options when the container is created.
  • tlsConfig is only non‑nil when TLS is actually enabled.

Please double-check that Run (and any other constructors) always populate settings correctly, including the non‑TLS path, so ConnectionHost never sees a zero‑value Options due to missed wiring. This will also keep behavior consistent with the TLSConfig accessor below.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

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

📒 Files selected for processing (1)
  • modules/cassandra/cassandra.go (4 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-29T13:57:14.636Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3319
File: modules/arangodb/arangodb.go:46-57
Timestamp: 2025-09-29T13:57:14.636Z
Learning: In testcontainers-go ArangoDB module, the wait strategy combines port listening check with HTTP readiness check using wait.ForAll - both strategies are required and complementary, not redundant.

Applied to files:

  • modules/cassandra/cassandra.go
📚 Learning: 2025-09-29T15:08:18.694Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3320
File: modules/artemis/artemis.go:98-103
Timestamp: 2025-09-29T15:08:18.694Z
Learning: In testcontainers-go, nat.Port is a type alias for string, so untyped string constants can be passed directly to functions expecting nat.Port (like wait.ForListeningPort) without explicit type conversion - the Go compiler handles the implicit conversion automatically.

Applied to files:

  • modules/cassandra/cassandra.go
🪛 GitHub Actions: Main pipeline
modules/cassandra/cassandra.go

[error] 1-1: syntax error: unexpected ) in composite literal; possibly missing comma or } (from golangci-lint)


[error] 90-90: syntax error: unexpected ) in composite literal; possibly missing comma or } (from golangci-lint)

⏰ 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)

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: 0

♻️ Duplicate comments (1)
modules/cassandra/cassandra.go (1)

40-44: Consider returning (*tls.Config, error) instead of *tls.Config

Right now callers have to infer “TLS not enabled” from a nil pointer. Exposing:

func (c *CassandraContainer) TLSConfig() (*tls.Config, error)

with an explicit error when TLS wasn’t enabled would align better with the pattern discussed for other modules (e.g. Redis/Valkey) and avoid silent misuse.

🧹 Nitpick comments (1)
modules/cassandra/cassandra.go (1)

120-161: Clarify interaction between WithTLS and WithConfigFile for cassandra.yaml

In the TLS branch you mount an embedded cassandra-ssl.yaml to /etc/cassandra/cassandra.yaml, and user options are appended afterwards:

moduleOpts = append(moduleOpts, opts...)

WithConfigFile also writes to /etc/cassandra/cassandra.yaml, so combining WithTLS() and WithConfigFile(...) means whichever runs last wins, which could silently disable the TLS configuration.

Consider either:

  • documenting that WithTLS should not be combined with WithConfigFile, or
  • detecting this combination and returning an error (or choosing a clear precedence) to avoid surprising behavior.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 879e285 and fd5772d.

⛔ Files ignored due to path filters (1)
  • modules/cassandra/go.sum is excluded by !**/*.sum
📒 Files selected for processing (7)
  • modules/cassandra/cassandra.go (4 hunks)
  • modules/cassandra/cassandra_test.go (1 hunks)
  • modules/cassandra/examples_test.go (1 hunks)
  • modules/cassandra/go.mod (1 hunks)
  • modules/cassandra/options.go (1 hunks)
  • modules/cassandra/testdata/cassandra-ssl.yaml (1 hunks)
  • modules/cassandra/tls.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • modules/cassandra/testdata/cassandra-ssl.yaml
  • modules/cassandra/options.go
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-18T08:24:27.479Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3254
File: .github/dependabot.yml:21-21
Timestamp: 2025-09-18T08:24:27.479Z
Learning: In the testcontainers-go repository, submodules like atlaslocal that are part of a parent module (e.g., mongodb) share the same go.mod file and should not have separate Dependabot entries. They are already monitored through the parent module's Dependabot configuration entry.

Applied to files:

  • modules/cassandra/go.mod
📚 Learning: 2025-09-29T13:57:14.636Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3319
File: modules/arangodb/arangodb.go:46-57
Timestamp: 2025-09-29T13:57:14.636Z
Learning: In testcontainers-go ArangoDB module, the wait strategy combines port listening check with HTTP readiness check using wait.ForAll - both strategies are required and complementary, not redundant.

Applied to files:

  • modules/cassandra/cassandra.go
📚 Learning: 2025-09-29T15:08:18.694Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3320
File: modules/artemis/artemis.go:98-103
Timestamp: 2025-09-29T15:08:18.694Z
Learning: In testcontainers-go, nat.Port is a type alias for string, so untyped string constants can be passed directly to functions expecting nat.Port (like wait.ForListeningPort) without explicit type conversion - the Go compiler handles the implicit conversion automatically.

Applied to files:

  • modules/cassandra/cassandra.go
🧬 Code graph analysis (3)
modules/cassandra/examples_test.go (3)
modules/cassandra/cassandra.go (1)
  • Run (90-176)
modules/cassandra/options.go (1)
  • WithTLS (42-47)
cleanup.go (1)
  • TerminateContainer (97-108)
modules/cassandra/cassandra_test.go (2)
modules/cassandra/cassandra.go (1)
  • Run (90-176)
modules/cassandra/options.go (1)
  • WithTLS (42-47)
modules/cassandra/cassandra.go (3)
modules/cassandra/options.go (1)
  • Option (19-19)
options.go (1)
  • WithFiles (524-529)
modules/redis/redis.go (1)
  • Run (58-139)
⏰ 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). (3)
  • GitHub Check: test (1.24.x, modules/cassandra) / test: modules/cassandra/1.24.x
  • GitHub Check: test (1.25.x, modules/cassandra) / test: modules/cassandra/1.25.x
  • GitHub Check: Analyze (go)
🔇 Additional comments (5)
modules/cassandra/go.mod (1)

7-13: TLS dependencies for Cassandra module look appropriate

The added module dependencies line up with the new TLS certificate and PKCS#12 handling in this module; no issues from a modularity or usage standpoint.

modules/cassandra/cassandra_test.go (1)

121-170: TLS integration test gives good end‑to‑end coverage

This test exercises the TLS option, validates that a TLS config is exposed, and runs real queries over the TLS connection, which is exactly what we need to guard the new behavior.

modules/cassandra/examples_test.go (1)

71-133: TLS example is clear and consistent with the non‑TLS example

The example mirrors the existing non‑TLS flow while showing how to enable TLS and use the exposed TLSConfig, so it’s a useful and consistent addition.

modules/cassandra/tls.go (1)

80-96: The proposed change to remove InsecureSkipVerify may introduce hostname verification failures

Setting InsecureSkipVerify: true is generally a security concern, but removing it without ensuring the self-signed certificate includes "localhost" as a Subject Alternative Name (SAN) or Common Name (CN) will cause TLS handshake failures. Certificates generated in container environments are typically issued for the container's hostname, not "localhost".

To properly address this:

  • Either regenerate the self-signed certificate to include "localhost" as a SAN, then remove InsecureSkipVerify: true
  • Or document why InsecureSkipVerify: true is necessary for this test-only setup and consider an alternative hostname that matches the cert

Simply removing the line without fixing the underlying hostname mismatch will break the tests.

modules/cassandra/cassandra.go (1)

91-99: Verify that the Option type includes the Customize method to implement ContainerCustomizer

The code at lines 91-99 correctly performs a type assertion to apply module-specific options, but this pattern requires Option to implement the testcontainers.ContainerCustomizer interface. According to the testcontainers-go module pattern, Option must define a Customize(req *testcontainers.GenericContainerRequest) error method (typically a no-op that returns nil) alongside its function signature type Option func(*options) error.

Without this method, callers passing cassandra.WithTLS() and similar option functions to Run as testcontainers.ContainerCustomizer parameters will either fail to compile or silently skip the option, leaving settings like tlsEnabled unset.

@MitulShah1
Copy link
Contributor Author

@mdelapenya @stevenh thanks for patience, i've fixed all issues please have a look again and let me know if any changes :)

@MitulShah1 MitulShah1 requested a review from stevenh December 5, 2025 07:35
mdelapenya
mdelapenya previously approved these changes Dec 5, 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.

LGTM! Thanks @MitulShah1 for your work and sorry for the late review. I just added a few comments regarding the missing docs, which are needed. But I'm already approving the PR waiting for the docs to be in place.

Cheers!

require.NoError(t, err)

// Verify TLS config is available
tlsConfig := ctr.TLSConfig()
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: could you add a check in the non-TLS tests that this config is nil?

// - Expose the SSL port (9142)
//
// Use TLSConfig() on the returned container to get the *tls.Config for client connections.
func WithTLS() Option {
Copy link
Member

Choose a reason for hiding this comment

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

bug: let's document the new option in the docs/modules/cassandra.md file. Please remember to use the marker as described in the contributing docs: https://golang.testcontainers.org/contributing/#adding-functional-options

It could be of interest to embed a code snippet linking to // withTLS { (see https://golang.testcontainers.org/contributing/#adding-code-snippets)


// TLSConfig returns the TLS configuration for secure client connections.
// Returns nil if TLS is not enabled on the container.
func (c *CassandraContainer) TLSConfig() *tls.Config {
Copy link
Member

Choose a reason for hiding this comment

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

bug: let's document the new container method in the docs/modules/cassandra.md file. Please remember to use the marker as described in the contributing docs: https://golang.testcontainers.org/contributing/#adding-functional-options

It could be of interest to embed a code snippet linking to // TLSConfig { (see https://golang.testcontainers.org/contributing/#adding-code-snippets)

Copy link
Member

Choose a reason for hiding this comment

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

BTW checking the rest of the comments, we agreed in having this method to return the pointer to tls.Config and an error. Let's change it

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 545a00e and ab26e27.

📒 Files selected for processing (4)
  • docs/modules/cassandra.md (1 hunks)
  • modules/cassandra/cassandra.go (4 hunks)
  • modules/cassandra/cassandra_test.go (1 hunks)
  • modules/cassandra/examples_test.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • modules/cassandra/examples_test.go
  • modules/cassandra/cassandra_test.go
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-09-29T13:57:14.636Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3319
File: modules/arangodb/arangodb.go:46-57
Timestamp: 2025-09-29T13:57:14.636Z
Learning: In testcontainers-go ArangoDB module, the wait strategy combines port listening check with HTTP readiness check using wait.ForAll - both strategies are required and complementary, not redundant.

Applied to files:

  • modules/cassandra/cassandra.go
📚 Learning: 2025-09-29T15:08:18.694Z
Learnt from: mdelapenya
Repo: testcontainers/testcontainers-go PR: 3320
File: modules/artemis/artemis.go:98-103
Timestamp: 2025-09-29T15:08:18.694Z
Learning: In testcontainers-go, nat.Port is a type alias for string, so untyped string constants can be passed directly to functions expecting nat.Port (like wait.ForListeningPort) without explicit type conversion - the Go compiler handles the implicit conversion automatically.

Applied to files:

  • modules/cassandra/cassandra.go
📚 Learning: 2025-11-05T11:57:09.224Z
Learnt from: natsoman
Repo: testcontainers/testcontainers-go PR: 3452
File: modules/cosmosdb/cosmosdb.go:11-14
Timestamp: 2025-11-05T11:57:09.224Z
Learning: In the testcontainers-go CosmosDB module (modules/azure/cosmosdb/), the defaultProtocol is intentionally set to "http" (not "https") to avoid requiring users to perform certificate setup steps (downloading and trusting the emulator's self-signed certificate). This design prioritizes ease of use for test containers over strict emulator fidelity.

Applied to files:

  • modules/cassandra/cassandra.go
🪛 GitHub Actions: Main pipeline
modules/cassandra/cassandra.go

[error] 44-44: golangci-lint: error-format: fmt.Errorf can be replaced with errors.New (perfsprint)

🪛 LanguageTool
docs/modules/cassandra.md

[grammar] ~73-~73: Ensure spelling is correct
Context: ...the container will fail to start. #### WithTLS - Not available until the next release <a ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

⏰ 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 (9)
modules/cassandra/cassandra.go (9)

4-7: LGTM!

The added imports support the TLS implementation correctly: bytes for config reader, crypto/tls for TLS types, and embed for bundling the SSL config file.


18-19: LGTM!

Standard Cassandra port definitions: 9042 for native protocol and 9142 for SSL-enabled native protocol.


22-23: LGTM!

Embedding the SSL configuration file is a good practice that ensures the TLS setup is self-contained within the module.


28-28: LGTM!

The settings field stores the container's options, including TLS state, which is necessary for the TLS feature implementation.


34-36: LGTM!

Correctly routes connection requests to the SSL port when TLS is enabled.


94-102: LGTM!

The option processing correctly implements the options pattern, extracting and applying custom options before container creation.


159-162: LGTM!

Adding a wait strategy for the SSL port ensures the container is fully ready before client connections are attempted. The use of WithAdditionalWaitStrategy properly complements the existing wait strategies.


105-105: Verify whether the non-SSL port should remain exposed when TLS is enabled.

Both the regular port (9042) and SSL port (9142) are exposed when TLS is enabled. If the non-SSL port remains functional, clients could bypass encryption, creating a security gap.

Confirm whether:

  1. The embedded cassandra-ssl.yaml configuration disables the non-SSL port (9042)
  2. It is intentional to allow both SSL and non-SSL connections simultaneously

Also applies to: 136-136


138-138: Confirm whether CASSANDRA_BROADCAST_RPC_ADDRESS should be "127.0.0.1" in a testcontainers context.

Setting CASSANDRA_BROADCAST_RPC_ADDRESS to 127.0.0.1 will cause clients connecting from the host machine to attempt connecting back to their own localhost when using Cassandra's cluster metadata discovery. While this may work for single-node test setups where clients don't rely on cluster metadata, it will break multi-node configurations and certain Cassandra driver behaviors that fetch node information from the cluster.

The standard pattern for testcontainers is to either use the container's internal bridge network address or rely on port mapping for discovery. Verify with a test that clients can successfully connect and discover nodes when this configuration is active.

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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d54d5f and 178c16f.

📒 Files selected for processing (1)
  • docs/modules/cassandra.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/modules/cassandra.md

[grammar] ~73-~73: Ensure spelling is correct
Context: ...the container will fail to start. #### WithTLS - Not available until the next release <a ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

⏰ 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). (3)
  • GitHub Check: test (1.25.x, modules/cassandra) / test: modules/cassandra/1.25.x
  • GitHub Check: test (1.24.x, modules/cassandra) / test: modules/cassandra/1.24.x
  • GitHub Check: Analyze (go)

@MitulShah1 MitulShah1 force-pushed the add-ssl-option-cassandra branch from 178c16f to 50579f9 Compare December 8, 2025 05:50
@MitulShah1 MitulShah1 requested a review from mdelapenya December 8, 2025 05:52
- Configure Cassandra to use client encryption
- Expose the SSL port (9142)

Use the `TLSConfig()` method on the returned container to get the `*tls.Config` for client connections. The method returns an error if TLS was not enabled via `WithTLS()`.
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: add the entry for the TLSConfig container method under 50579f9#diff-b27ccdbcf3e3815b7df9845a916f9fec349d71ad4f2baa18ce80edc5dd84bf8fR92, which is the dedicated section for them.

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