Skip to content

Commit 74ac112

Browse files
committed
Adding support for Cassandra and Scylla
This add the support for those cassandra based dbs and their drivers, cassandra-driver, scylla-driver Ref: https://cassandra.apache.org/ Ref: https://www.scylladb.com/ Ref: https://pypi.org/project/cassandra-driver/ Ref: https://pypi.org/project/scylla-driver/
1 parent f899846 commit 74ac112

File tree

8 files changed

+124
-1
lines changed

8 files changed

+124
-1
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ jobs:
3131
- webdriver.py
3232
- keycloak.py
3333
- arangodb.py
34+
- scylladb.py
35+
- cassandra.py
3436
runs-on: ubuntu-latest
3537
steps:
3638
- uses: actions/checkout@v2

docs/database.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ Allows to spin up database images such as MySQL, PostgreSQL, MariaDB, Oracle XE,
1313
.. autoclass:: testcontainers.clickhouse.ClickHouseContainer
1414
.. autoclass:: testcontainers.neo4j.Neo4jContainer
1515
.. autoclass:: testcontainers.arangodb.ArangoDbContainer
16+
.. autoclass:: testcontainers.cassandra.CassandraContainer
17+
.. autoclass:: testcontainers.scylla.ScyllaContainer

requirements.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
-e file:.[docker-compose,mysql,oracle,postgresql,selenium,google-cloud-pubsub,mongo,redis,mssqlserver,neo4j,kafka,rabbitmq,clickhouse,keycloak,arangodb]
1+
-e file:.[docker-compose,mysql,oracle,postgresql,selenium,google-cloud-pubsub,mongo,redis,mssqlserver,neo4j,kafka,rabbitmq,clickhouse,keycloak,arangodb,cassandra,scylla]
22
codecov>=2.1.0
33
cryptography<37
44
flake8<3.8.0 # 3.8.0 adds a dependency on importlib-metadata which conflicts with other packages.

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@
6868
'clickhouse': ['clickhouse-driver'],
6969
'keycloak': ['python-keycloak'],
7070
'arangodb': ['python-arango'],
71+
'cassandra': ['cassandra-driver'],
72+
'scylla': ['scylla-driver']
7173
},
7274
long_description_content_type="text/x-rst",
7375
long_description=long_description,

testcontainers/cassandra.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from testcontainers.core.generic import DockerContainer
2+
from testcontainers.core.waiting_utils import wait_container_is_ready
3+
4+
5+
class CassandraContainer(DockerContainer):
6+
"""
7+
Cassandra database container.
8+
9+
Example
10+
-------
11+
::
12+
13+
with CassandraContainer() as cassandra:
14+
cluster = cassandra.get_cluster()
15+
with cluster.connect() as session:
16+
session.execute(
17+
"CREATE KEYSPACE keyspace1 WITH replication = "
18+
"{'class': 'SimpleStrategy', 'replication_factor': '1'};")
19+
20+
"""
21+
def __init__(self, image="rinscy/cassandra:latest", ports_to_expose=[9042]):
22+
super(CassandraContainer, self).__init__(image)
23+
self.ports_to_expose = ports_to_expose
24+
self.with_exposed_ports(*self.ports_to_expose)
25+
26+
@wait_container_is_ready()
27+
def _connect(self):
28+
cluster = self.get_cluster()
29+
cluster.connect()
30+
31+
def start(self):
32+
super(CassandraContainer, self).start()
33+
self._connect()
34+
return self
35+
36+
def get_cluster(self, **kwargs):
37+
from cassandra.cluster import Cluster
38+
hostname = self.get_container_host_ip()
39+
port = self.get_exposed_port(9042)
40+
return Cluster(contact_points=[hostname], port=port, **kwargs)

testcontainers/scylla.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from testcontainers.core.generic import DockerContainer
2+
from testcontainers.core.waiting_utils import wait_container_is_ready
3+
4+
5+
class ScyllaContainer(DockerContainer):
6+
"""
7+
Scylla database container.
8+
9+
Example
10+
-------
11+
::
12+
13+
with ScyllaContainer() as scylla:
14+
cluster = scylla.get_cluster()
15+
with cluster.connect() as session:
16+
session.execute(
17+
"CREATE KEYSPACE keyspace1 WITH replication "
18+
"= {'class': 'SimpleStrategy', 'replication_factor': '1'};")
19+
20+
"""
21+
def __init__(self, image="scylladb/scylla:4.6.rc1", ports_to_expose=[9042]):
22+
super(ScyllaContainer, self).__init__(image)
23+
self.ports_to_expose = ports_to_expose
24+
self.with_exposed_ports(*self.ports_to_expose)
25+
self.with_command("--skip-wait-for-gossip-to-settle=0")
26+
27+
@wait_container_is_ready()
28+
def _connect(self):
29+
cluster = self.get_cluster()
30+
cluster.connect()
31+
32+
def start(self):
33+
super(ScyllaContainer, self).start()
34+
self._connect()
35+
return self
36+
37+
def get_cluster(self, **kwargs):
38+
from cassandra.cluster import Cluster
39+
hostname = self.get_container_host_ip()
40+
port = self.get_exposed_port(9042)
41+
return Cluster(contact_points=[hostname], port=port, **kwargs)

tests/test_cassandra.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from testcontainers.cassandra import CassandraContainer
2+
3+
4+
def test_docker_run_cassandra():
5+
with CassandraContainer() as cassandra:
6+
cluster = cassandra.get_cluster()
7+
with cluster.connect() as session:
8+
session.execute(
9+
"CREATE KEYSPACE keyspace1 WITH replication = "
10+
"{'class': 'SimpleStrategy', 'replication_factor': '1'};")
11+
session.execute(
12+
"CREATE TABLE keyspace1.table1 (key1 int, key2 int, PRIMARY KEY (key1));")
13+
session.execute("INSERT INTO keyspace1.table1 (key1,key2) values (1,2);")
14+
15+
response = session.execute("SELECT * FROM keyspace1.table1")
16+
17+
assert response.one().key1 == 1
18+
assert response.one().key2 == 2

tests/test_scylla.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from testcontainers.scylla import ScyllaContainer
2+
3+
4+
def test_docker_run_scylla():
5+
with ScyllaContainer() as scylla:
6+
cluster = scylla.get_cluster()
7+
with cluster.connect() as session:
8+
session.execute(
9+
"CREATE KEYSPACE keyspace1 WITH replication = "
10+
"{'class': 'SimpleStrategy', 'replication_factor': '1'};")
11+
session.execute(
12+
"CREATE TABLE keyspace1.table1 (key1 int, key2 int, PRIMARY KEY (key1));")
13+
session.execute("INSERT INTO keyspace1.table1 (key1,key2) values (1,2);")
14+
15+
response = session.execute("SELECT * FROM keyspace1.table1")
16+
17+
assert response.one().key1 == 1
18+
assert response.one().key2 == 2

0 commit comments

Comments
 (0)