Skip to content

Commit f907a7e

Browse files
feat: add Cassandra image (#460)
1 parent c3286eb commit f907a7e

3 files changed

Lines changed: 90 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ watchdog = ["testcontainers/watchdog"]
2727
json = ["serde", "serde_json"]
2828
anvil = []
2929
arrow_flightsql = []
30+
cassandra = []
3031
clickhouse = ["http_wait"]
3132
cratedb = []
3233
cncf_distribution = []

src/cassandra/mod.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use testcontainers::{core::WaitFor, Image};
2+
3+
const NAME: &str = "cassandra";
4+
const TAG: &str = "5.0.6";
5+
6+
/// Module to work with [`Cassandra`] inside of tests.
7+
///
8+
/// This module is based on the official [`Cassandra docker image`].
9+
///
10+
/// # Example
11+
/// ```
12+
/// use scylla::client::{session::Session, session_builder::SessionBuilder};
13+
/// use std::time::Duration;
14+
/// use testcontainers::{runners::AsyncRunner, ImageExt};
15+
///
16+
/// #[tokio::test]
17+
/// async fn default_cassandra() -> Result<(), Box<dyn std::error::Error + 'static>> {
18+
/// let image = ScyllaDB::default();
19+
/// let instance = image.start().await?;
20+
/// let host = instance.get_host().await?;
21+
/// let port = instance.get_host_port_ipv4(9042).await?;
22+
/// let hostname = format!("{host}:{port}");
23+
/// let session: Session = SessionBuilder::new().known_node(hostname).build().await?;
24+
///
25+
/// let prepared_statement = session
26+
/// .prepare("SELECT release_version FROM system.local")
27+
/// .await?;
28+
/// let rows = session
29+
/// .execute_unpaged(&prepared_statement, &[])
30+
/// .await?
31+
/// .into_rows_result()?;
32+
/// let (version,) = rows.single_row::<(String,)>()?;
33+
/// assert_eq!(version, "5.0.6");
34+
/// Ok(())
35+
/// }
36+
/// ```
37+
///
38+
/// [`Cassandra`]: https://cassandra.apache.org
39+
/// [`Cassandra docker image`]: https://hub.docker.com/_/cassandra
40+
#[derive(Default, Clone, Debug)]
41+
pub struct Cassandra {}
42+
43+
impl Image for Cassandra {
44+
fn name(&self) -> &str {
45+
NAME
46+
}
47+
48+
fn tag(&self) -> &str {
49+
TAG
50+
}
51+
52+
fn ready_conditions(&self) -> Vec<WaitFor> {
53+
vec![WaitFor::message_on_either_std("Startup complete")]
54+
}
55+
}
56+
57+
#[cfg(test)]
58+
mod tests {
59+
use scylla::client::{session::Session, session_builder::SessionBuilder};
60+
use std::time::Duration;
61+
use testcontainers::{runners::AsyncRunner, ImageExt};
62+
63+
use super::*;
64+
65+
#[tokio::test]
66+
async fn cassandra_select_version() -> Result<(), Box<dyn std::error::Error + 'static>> {
67+
let image = Cassandra::default().with_startup_timeout(Duration::from_secs(240));
68+
let instance = image.start().await?;
69+
let host = instance.get_host().await?;
70+
let port = instance.get_host_port_ipv4(9042).await?;
71+
let hostname = format!("{host}:{port}");
72+
let session: Session = SessionBuilder::new().known_node(hostname).build().await?;
73+
74+
let prepared_statement = session
75+
.prepare("SELECT release_version FROM system.local")
76+
.await?;
77+
let rows = session
78+
.execute_unpaged(&prepared_statement, &[])
79+
.await?
80+
.into_rows_result()?;
81+
let (version,) = rows.single_row::<(String,)>()?;
82+
assert_eq!(version, "5.0.6");
83+
Ok(())
84+
}
85+
}

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ pub mod arrow_flightsql;
2020
#[cfg_attr(docsrs, doc(cfg(feature = "azurite")))]
2121
/// **Azurite** (azure storage emulator) testcontainer
2222
pub mod azurite;
23+
#[cfg(feature = "cassandra")]
24+
#[cfg_attr(docsrs, doc(cfg(feature = "cassandra")))]
25+
/// **Cassandra** (distributed NoSQL wide-column data store) testcontainer
26+
pub mod cassandra;
2327
#[cfg(feature = "clickhouse")]
2428
#[cfg_attr(docsrs, doc(cfg(feature = "clickhouse")))]
2529
/// **Clickhouse** (analytics database) testcontainer

0 commit comments

Comments
 (0)