Skip to content

ScyllaDB

Since v0.36.0

Introduction

The Testcontainers module for ScyllaDB, a NoSQL database fully compatible with Apache Cassandra and DynamoDB, allows you to create a ScyllaDB container for testing purposes.

Adding this module to your project dependencies

Please run the following command to add the ScyllaDB module to your Go dependencies:

go get github.com/testcontainers/testcontainers-go/modules/scylladb

Usage example

    ctx := context.Background()

    // runScyllaDBContainerWithCustomCommands {
    scyllaContainer, err := scylladb.Run(ctx,
        "scylladb/scylla:6.2",
        scylladb.WithCustomCommands("--memory=1G", "--smp=2"),
    )
    // }
    defer func() {
        if err := testcontainers.TerminateContainer(scyllaContainer); err != nil {
            log.Printf("failed to terminate container: %s", err)
        }
    }()
    if err != nil {
        log.Printf("failed to start container: %s", err)
        return
    }

    state, err := scyllaContainer.State(ctx)
    if err != nil {
        log.Printf("failed to get container state: %s", err)
        return
    }

    fmt.Println(state.Running)

    connectionHost, err := scyllaContainer.NonShardAwareConnectionHost(ctx)
    if err != nil {
        log.Printf("failed to get connection host: %s", err)
        return
    }

    if err := runGoCQLExampleTest(connectionHost); err != nil {
        log.Printf("failed to run Go CQL example test: %s", err)
        return
    }

    // Output:
    // true

 

    ctx := context.Background()

    // runScyllaDBContainerWithAlternator {

    scyllaContainer, err := scylladb.Run(ctx,
        "scylladb/scylla:6.2",
        scylladb.WithAlternator(),
    )
    // }
    defer func() {
        if err := testcontainers.TerminateContainer(scyllaContainer); err != nil {
            log.Printf("failed to terminate container: %s", err)
        }
    }()
    if err != nil {
        log.Printf("failed to start container: %s", err)
        return
    }

    state, err := scyllaContainer.State(ctx)
    if err != nil {
        log.Printf("failed to get container state: %s", err)
        return
    }

    fmt.Println(state.Running)

    // scyllaDbAlternatorConnectionHost {
    // the alternator port is the default port 8000
    _, err = scyllaContainer.AlternatorConnectionHost(ctx)
    // }
    if err != nil {
        log.Printf("failed to get connection host: %s", err)
        return
    }

    // Output:
    // true

 

    ctx := context.Background()

    // runScyllaDBContainerWithShardAwareness {
    scyllaContainer, err := scylladb.Run(ctx,
        "scylladb/scylla:6.2",
        scylladb.WithShardAwareness(),
    )
    // }
    defer func() {
        if err := testcontainers.TerminateContainer(scyllaContainer); err != nil {
            log.Printf("failed to terminate container: %s", err)
        }
    }()
    if err != nil {
        log.Printf("failed to start container: %s", err)
        return
    }

    state, err := scyllaContainer.State(ctx)
    if err != nil {
        log.Printf("failed to get container state: %s", err)
        return
    }

    fmt.Println(state.Running)

    // scyllaDbShardAwareConnectionHost {
    connectionHost, err := scyllaContainer.ShardAwareConnectionHost(ctx)
    // }
    if err != nil {
        log.Printf("failed to get connection host: %s", err)
        return
    }

    if err := runGoCQLExampleTest(connectionHost); err != nil {
        log.Printf("failed to run Go CQL example test: %s", err)
        return
    }

    // Output:
    // true

 

    // runScyllaDBContainerWithConfig {
    ctx := context.Background()

    cfgBytes := `cluster_name: 'Amazing ScyllaDB Test'
num_tokens: 256
commitlog_sync: periodic
commitlog_sync_period_in_ms: 10000
commitlog_segment_size_in_mb: 32
schema_commitlog_segment_size_in_mb: 128
seed_provider:
  - class_name: org.apache.cassandra.locator.SimpleSeedProvider
    parameters:
      - seeds: "127.0.0.1"
listen_address: localhost
native_transport_port: 9042
native_shard_aware_transport_port: 19042
read_request_timeout_in_ms: 5000
write_request_timeout_in_ms: 2000
cas_contention_timeout_in_ms: 1000
endpoint_snitch: SimpleSnitch
rpc_address: localhost
api_port: 10000
api_address: 127.0.0.1
batch_size_warn_threshold_in_kb: 128
batch_size_fail_threshold_in_kb: 1024
partitioner: org.apache.cassandra.dht.Murmur3Partitioner
commitlog_total_space_in_mb: -1
murmur3_partitioner_ignore_msb_bits: 12
strict_is_not_null_in_views: true
maintenance_socket: ignore
enable_tablets: true
`

    scyllaContainer, err := scylladb.Run(ctx,
        "scylladb/scylla:6.2",
        scylladb.WithConfig(strings.NewReader(cfgBytes)),
    )
    // }
    defer func() {
        if err := testcontainers.TerminateContainer(scyllaContainer); err != nil {
            log.Printf("failed to terminate container: %s", err)
        }
    }()
    if err != nil {
        log.Printf("failed to start container: %s", err)
        return
    }

 

    // runBaseScyllaDBContainer {
    ctx := context.Background()

    scyllaContainer, err := scylladb.Run(ctx,
        "scylladb/scylla:6.2",
        scylladb.WithShardAwareness(),
    )
    defer func() {
        if err := testcontainers.TerminateContainer(scyllaContainer); err != nil {
            log.Printf("failed to terminate container: %s", err)
        }
    }()
    if err != nil {
        log.Printf("failed to start container: %s", err)
        return
    }
    // }

    state, err := scyllaContainer.State(ctx)
    if err != nil {
        log.Printf("failed to get container state: %s", err)
        return
    }

    fmt.Println(state.Running)

    // scyllaDbNonShardAwareConnectionHost {
    connectionHost, err := scyllaContainer.NonShardAwareConnectionHost(ctx)
    // }
    if err != nil {
        log.Printf("failed to get connection host: %s", err)
        return
    }

    if err := runGoCQLExampleTest(connectionHost); err != nil {
        log.Printf("failed to run Go CQL example test: %s", err)
        return
    }

    // Output:
    // true

Module Reference

Run function

The ScyllaDB module exposes one entrypoint function to create the ScyllaDB container, and this function receives three parameters:

func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustomizer) (*Container, error)
  • context.Context, the Go context.
  • string, the Docker image to use.
  • testcontainers.ContainerCustomizer, a variadic argument for passing options.

Info

By default, we add the --developer-mode=1 flag to the ScyllaDB container to disable the various checks Scylla performs. Also in scenarios in which static partitioning is not desired - like mostly-idle cluster without hard latency requirements, the --overprovisioned command-line option is recommended. This enables certain optimizations for ScyllaDB to run efficiently in an overprovisioned environment. You can change it by using the WithCustomCommand function.

Image

Use the second argument in the Run function to set a valid Docker image. In example:

scylladb.Run(context.Background(), "scylladb/scylla:6.2.1")
// OR
scylladb.Run(context.Background(), "scylladb/scylla:5.6")

Container Options

When starting the ScyllaDB container, you can pass options in a variadic way to configure it.

With Database Configuration File (scylla.yaml)

In the case you have a custom config file for ScyllaDB, it's possible to copy that file into the container before it's started, using the WithConfig(r io.Reader) function.

    ctx := context.Background()

    cfgBytes := `cluster_name: 'Amazing ScyllaDB Test'
num_tokens: 256
commitlog_sync: periodic
commitlog_sync_period_in_ms: 10000
commitlog_segment_size_in_mb: 32
schema_commitlog_segment_size_in_mb: 128
seed_provider:
  - class_name: org.apache.cassandra.locator.SimpleSeedProvider
    parameters:
      - seeds: "127.0.0.1"
listen_address: localhost
native_transport_port: 9042
native_shard_aware_transport_port: 19042
read_request_timeout_in_ms: 5000
write_request_timeout_in_ms: 2000
cas_contention_timeout_in_ms: 1000
endpoint_snitch: SimpleSnitch
rpc_address: localhost
api_port: 10000
api_address: 127.0.0.1
batch_size_warn_threshold_in_kb: 128
batch_size_fail_threshold_in_kb: 1024
partitioner: org.apache.cassandra.dht.Murmur3Partitioner
commitlog_total_space_in_mb: -1
murmur3_partitioner_ignore_msb_bits: 12
strict_is_not_null_in_views: true
maintenance_socket: ignore
enable_tablets: true
`

    scyllaContainer, err := scylladb.Run(ctx,
        "scylladb/scylla:6.2",
        scylladb.WithConfig(strings.NewReader(cfgBytes)),
    )

Warning

You should provide a valid ScyllaDB configuration file as an io.Reader when using the function, otherwise the container will fail to start. The configuration file should be a valid YAML file and follows the ScyllaDB configuration file.

With Shard Awareness

If you want to test ScyllaDB with shard awareness, you can use the WithShardAwareness function. This function will configure the ScyllaDB container to use the 19042 port and ask the container to wait until the port is ready.

scyllaContainer, err := scylladb.Run(ctx,
    "scylladb/scylla:6.2",
    scylladb.WithShardAwareness(),
)

With Alternator (DynamoDB Compatible API)

If you want to test ScyllaDB with the Alternator API, you can use the WithAlternator function. This function will configure the ScyllaDB container to use the port any port you want and ask the container to wait until the port is ready. By default, you can choose the port 8000.

scyllaContainer, err := scylladb.Run(ctx,
    "scylladb/scylla:6.2",
    scylladb.WithAlternator(),
)

With Custom Commands

If you need to pass any flag to the ScyllaDB container, you can use the WithCustomCommand function. This also rewrites predefined commands like --developer-mode=1. You can check the ScyllaDB Docker Best Practices for more information.

scyllaContainer, err := scylladb.Run(ctx,
    "scylladb/scylla:6.2",
    scylladb.WithCustomCommands("--memory=1G", "--smp=2"),
)

The following options are exposed by the testcontainers package.

Basic Options

Lifecycle Options

Files & Mounts Options

Build Options

Logging Options

Image Options

Networking Options

Advanced Options

Experimental Options

Container Methods

The ScyllaDB container exposes the following methods:

ConnectionHost methods

There exist three methods to get the host and port of the ScyllaDB container, depending on the feature you want.

If you just want to test it with a single node and a single core, you can use the NonShardAwareConnectionHost method. However, if you're planning to use more than one core, you should use the ShardAwareConnectionHost method, which uses the shard-awareness 19042 port.

Else, if you're planning to use the Alternator API, you should use the AlternatorConnectionHost method, which uses the default port 8000.

connectionHost, err := scyllaContainer.NonShardAwareConnectionHost(ctx)
connectionHost, err := scyllaContainer.ShardAwareConnectionHost(ctx)
// the alternator port is the default port 8000
_, err = scyllaContainer.AlternatorConnectionHost(ctx)