Skip to content

Commit

Permalink
feat: add RQLite module (#261)
Browse files Browse the repository at this point in the history
  • Loading branch information
Spirans authored Jan 7, 2025
1 parent 1332833 commit 56bbb8a
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 4 deletions.
24 changes: 20 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,16 @@ zookeeper = []
cockroach_db = []
kwok = []
pulsar = []
rqlite = ["http_wait"]

[dependencies]
# TODO: update parse-display after MSRV>=1.80.0 bump of `testcontainer-rs` and `testcontainers-modules`
parse-display = { version = "0.9.1", optional = true, default-features = false, features = [] }
rcgen = { version = "0.13.1", features = ["pem", "ring"], default-features = false, optional = true }
parse-display = { version = "0.9.1", optional = true, default-features = false, features = [
] }
rcgen = { version = "0.13.1", features = [
"pem",
"ring",
], default-features = false, optional = true }
testcontainers = { version = "0.23.0" }


Expand Down Expand Up @@ -101,17 +106,24 @@ tar = "0.4.40"
testcontainers = { version = "0.23.0", features = ["blocking"] }
# To use Tiberius on macOS, rustls is needed instead of native-tls
# https://github.com/prisma/tiberius/tree/v0.12.2#encryption-tlsssl
tiberius = { version = "0.12.2", default-features = false, features = ["tds73", "rustls"] }
tiberius = { version = "0.12.2", default-features = false, features = [
"tds73",
"rustls",
] }
tokio = { version = "1", features = ["macros"] }
tokio-util = { version = "0.7.10", features = ["compat"] }
zookeeper-client = { version = "0.8.0" }
kube = { version = "0.90.0", default-features = false, features = ["client", "rustls-tls"] }
kube = { version = "0.90.0", default-features = false, features = [
"client",
"rustls-tls",
] }
k8s-openapi = { version = "0.21.1", features = ["v1_29"] }
clickhouse = "0.11.6"
vaultrs = "0.7.2"
openssl-sys = { version = "0.9.103", features = ["vendored"] }
native-tls = { version = "0.2.12", features = ["vendored"] }
pulsar = "6.3"
rqlite-rs = "0.5.0"

[[example]]
name = "postgres"
Expand Down Expand Up @@ -144,3 +156,7 @@ required-features = ["openldap"]
[[example]]
name = "nats"
required-features = ["nats"]

[[example]]
name = "rqlite"
required-features = ["rqlite"]
24 changes: 24 additions & 0 deletions examples/rqlite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use testcontainers::runners::AsyncRunner;
use testcontainers_modules::rqlite::RQLite;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
let _ = pretty_env_logger::try_init();

let node = RQLite::default().start().await?;
let host_ip = node.get_host().await?;
let host_port = node.get_host_port_ipv4(4001).await?;

let client = rqlite_rs::RqliteClientBuilder::new()
.known_host(format!("{}:{}", host_ip, host_port))
.build()?;

let query = rqlite_rs::query!("SELECT 1+1")?;
let rows = client.fetch(query).await?;
assert_eq!(rows.len(), 1);

let first_row = &rows[0];
let first_column: i32 = first_row.get("1+1")?;
assert_eq!(first_column, 2);
Ok(())
}
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ pub mod rabbitmq;
#[cfg_attr(docsrs, doc(cfg(feature = "redis")))]
/// **redis** (in memory nosql database) testcontainer
pub mod redis;
#[cfg(feature = "rqlite")]
#[cfg_attr(docsrs, doc(cfg(feature = "rqlite")))]
/// **RQLite** (lightweight, user-friendly, distributed relational database) testcontainer
pub mod rqlite;
#[cfg(feature = "solr")]
#[cfg_attr(docsrs, doc(cfg(feature = "solr")))]
/// **Apache Solr** (distributed search engine) testcontainer
Expand Down
87 changes: 87 additions & 0 deletions src/rqlite/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use testcontainers::{
core::{wait::HttpWaitStrategy, ContainerPort, WaitFor},
Image,
};

/// Port that the [`RQLite`] container has internally
/// Can be rebound externally via [`testcontainers::core::ImageExt::with_mapped_port`]
///
/// [`RQLite`]: https://rqlite.io/
pub const RQLITE_PORT: ContainerPort = ContainerPort::Tcp(4001);

const NAME: &str = "rqlite/rqlite";
const TAG: &str = "8.36.3";

/// Module to work with [`RQLite`] inside of tests.
///
/// This module is based on the official [`RQLite docker image`].
///
/// # Example
/// ```
/// use testcontainers_modules::{rqlite, testcontainers::runners::SyncRunner};
///
/// let rqlite = rqlite::RQLite::default().start().unwrap();
/// let http_port = rqlite.get_host_port_ipv4(4001).unwrap();
///
/// // do something with the started rqlite instance..
/// ```
///
/// [`RQLite`]: https://rqlite.io/
/// [`RQLite docker image`]: https://hub.docker.com/r/rqlite/rqlite/
#[derive(Debug, Default, Clone)]
pub struct RQLite {
/// (remove if there is another variable)
/// Field is included to prevent this struct to be a unit struct.
/// This allows extending functionality (and thus further variables) without breaking changes
_priv: (),
}

impl Image for RQLite {
fn name(&self) -> &str {
NAME
}

fn tag(&self) -> &str {
TAG
}

fn ready_conditions(&self) -> Vec<WaitFor> {
vec![
WaitFor::http(HttpWaitStrategy::new("/status").with_expected_status_code(200_u16)),
WaitFor::message_on_stderr("is now Leader"),
]
}

fn expose_ports(&self) -> &[ContainerPort] {
&[RQLITE_PORT]
}
}

#[cfg(test)]
mod tests {
use testcontainers::runners::AsyncRunner;

use crate::rqlite::RQLite;

#[tokio::test]
async fn rqlite_db() -> Result<(), Box<dyn std::error::Error + 'static>> {
let _ = pretty_env_logger::try_init();
let node = RQLite::default().start().await?;
let host_ip = node.get_host().await?;
let host_port = node.get_host_port_ipv4(4001).await?;

let client = rqlite_rs::RqliteClientBuilder::new()
.known_host(format!("{}:{}", host_ip, host_port))
.build()?;

let query = rqlite_rs::query!("SELECT 1+1")?;
let rows = client.fetch(query).await?;
assert_eq!(rows.len(), 1);

let first_row = &rows[0];
let first_column: i32 = first_row.get("1+1")?;
assert_eq!(first_column, 2);

Ok(())
}
}

0 comments on commit 56bbb8a

Please sign in to comment.