This is an automated email from the ASF dual-hosted git repository.
absurdfarce pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra-python-driver.git
The following commit(s) were added to refs/heads/trunk by this push:
new 88bf5850 CASSPYTHON-23 Remove CloudTests and CloudSchemaTests
88bf5850 is described below
commit 88bf585090a3082587458d46a8d5be22574c6fe0
Author: absurdfarce <[email protected]>
AuthorDate: Thu Jun 11 17:02:51 2026 -0500
CASSPYTHON-23 Remove CloudTests and CloudSchemaTests
patch by Bret McGuire; reviewed by Bret McGuire and Brad Schoening
reference: https://github.com/apache/cassandra-python-driver/pull/1296
---
Jenkinsfile | 18 --
tests/integration/cloud/__init__.py | 113 -------------
tests/integration/cloud/conftest.py | 10 --
tests/integration/cloud/test_cloud.py | 244 ---------------------------
tests/integration/cloud/test_cloud_schema.py | 118 -------------
5 files changed, 503 deletions(-)
diff --git a/Jenkinsfile b/Jenkinsfile
index 46624d57..fa4a4311 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -392,24 +392,6 @@ def executeStandardTests() {
}
}
- try {
- sh label: 'Execute DataStax Astra integration tests', script:
'''#!/bin/bash -lex
- . ./jenkins-venv/bin/activate
-
- # Load CCM environment variable
- set -o allexport
- . ${HOME}/environment.txt
- set +o allexport
-
- . ${JABBA_SHELL}
- jabba use 1.8
-
- EVENT_LOOP=${EVENT_LOOP} CLOUD_PROXY_PATH="${HOME}/proxy/"
CASSANDRA_VERSION=${CCM_CASSANDRA_VERSION}
MAPPED_CASSANDRA_VERSION=${MAPPED_CASSANDRA_VERSION}
VERIFY_CYTHON=${CYTHON_ENABLED} JVM_EXTRA_OPTS="$JVM_EXTRA_OPTS -Xss384k"
pytest -s -v --log-format="[%(levelname)s] %(asctime)s %(thread)d: %(message)s"
--junit-xml=advanced_results.xml tests/integration/cloud/
- '''
- } catch (err) {
- currentBuild.result = 'UNSTABLE'
- }
-
if (env.PROFILE == 'FULL') {
try {
sh label: 'Execute long running integration tests', script:
'''#!/bin/bash -lex
diff --git a/tests/integration/cloud/__init__.py
b/tests/integration/cloud/__init__.py
deleted file mode 100644
index a6a4ab7a..00000000
--- a/tests/integration/cloud/__init__.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# Copyright DataStax, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License
-from cassandra.cluster import Cluster
-
-import unittest
-
-import os
-import subprocess
-
-from tests.integration import CLOUD_PROXY_PATH, USE_CASS_EXTERNAL
-
-
-def setup_package():
- if CLOUD_PROXY_PATH and not USE_CASS_EXTERNAL:
- start_cloud_proxy()
-
-
-def teardown_package():
- if not USE_CASS_EXTERNAL:
- stop_cloud_proxy()
-
-
-class CloudProxyCluster(unittest.TestCase):
-
- creds_dir = os.path.join(os.path.abspath(CLOUD_PROXY_PATH or ''),
'certs/bundles/')
- creds = os.path.join(creds_dir, 'creds-v1.zip')
- creds_no_auth = os.path.join(creds_dir, 'creds-v1-wo-creds.zip')
- creds_unreachable = os.path.join(creds_dir, 'creds-v1-unreachable.zip')
- creds_invalid_ca = os.path.join(creds_dir, 'creds-v1-invalid-ca.zip')
-
- cluster, connect = None, False
- session = None
-
- @classmethod
- def connect(cls, creds, **kwargs):
- cloud_config = {
- 'secure_connect_bundle': creds,
- }
- cls.cluster = Cluster(cloud=cloud_config, protocol_version=4, **kwargs)
- cls.session = cls.cluster.connect(wait_for_all_pools=True)
-
- def tearDown(self):
- if self.cluster:
- self.cluster.shutdown()
-
-
-class CloudProxyServer(object):
- """
- Class for starting and stopping the proxy (sni_single_endpoint)
- """
-
- ccm_command = 'docker exec $(docker ps -a -q --filter
ancestor=single_endpoint) ccm {}'
-
- def __init__(self, CLOUD_PROXY_PATH):
- self.CLOUD_PROXY_PATH = CLOUD_PROXY_PATH
- self.running = False
-
- def start(self):
- return_code = subprocess.call(
- ['REQUIRE_CLIENT_CERTIFICATE=true ./run.sh'],
- cwd=self.CLOUD_PROXY_PATH,
- shell=True)
- if return_code != 0:
- raise Exception("Error while starting proxy server")
- self.running = True
-
- def stop(self):
- if self.is_running():
- subprocess.call(
- ["docker kill $(docker ps -a -q --filter
ancestor=single_endpoint)"],
- shell=True)
- self.running = False
-
- def is_running(self):
- return self.running
-
- def start_node(self, id):
- subcommand = 'node{} start --jvm_arg
"-Ddse.product_type=DATASTAX_APOLLO" --root --wait-for-binary-proto'.format(id)
- subprocess.call(
- [self.ccm_command.format(subcommand)],
- shell=True)
-
- def stop_node(self, id):
- subcommand = 'node{} stop'.format(id)
- subprocess.call(
- [self.ccm_command.format(subcommand)],
- shell=True)
-
-
-CLOUD_PROXY_SERVER = CloudProxyServer(CLOUD_PROXY_PATH)
-
-
-def start_cloud_proxy():
- """
- Starts and waits for the proxy to run
- """
- CLOUD_PROXY_SERVER.stop()
- CLOUD_PROXY_SERVER.start()
-
-
-def stop_cloud_proxy():
- CLOUD_PROXY_SERVER.stop()
diff --git a/tests/integration/cloud/conftest.py
b/tests/integration/cloud/conftest.py
deleted file mode 100644
index 6bfda325..00000000
--- a/tests/integration/cloud/conftest.py
+++ /dev/null
@@ -1,10 +0,0 @@
-import pytest
-
-from tests.integration.cloud import setup_package, teardown_package
-
-
[email protected](scope='session', autouse=True)
-def setup_and_teardown_packages():
- setup_package()
- yield
- teardown_package()
diff --git a/tests/integration/cloud/test_cloud.py
b/tests/integration/cloud/test_cloud.py
deleted file mode 100644
index 1c1e75c1..00000000
--- a/tests/integration/cloud/test_cloud.py
+++ /dev/null
@@ -1,244 +0,0 @@
-# Copyright DataStax, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License
-from cassandra.datastax.cloud import parse_metadata_info
-from cassandra.query import SimpleStatement
-from cassandra.cqlengine import connection
-from cassandra.cqlengine.management import sync_table, create_keyspace_simple
-from cassandra.cqlengine.models import Model
-from cassandra.cqlengine import columns
-
-import unittest
-
-from ssl import SSLContext, PROTOCOL_TLS
-
-from cassandra import DriverException, ConsistencyLevel, InvalidRequest
-from cassandra.cluster import NoHostAvailable, ExecutionProfile, Cluster,
_execution_profile_to_string
-from cassandra.connection import SniEndPoint
-from cassandra.auth import PlainTextAuthProvider
-from cassandra.policies import TokenAwarePolicy, DCAwareRoundRobinPolicy,
ConstantReconnectionPolicy
-
-from unittest.mock import patch
-
-from tests.integration import requirescloudproxy
-from tests.util import wait_until_not_raised
-from tests.integration.cloud import CloudProxyCluster, CLOUD_PROXY_SERVER
-
-DISALLOWED_CONSISTENCIES = [
- ConsistencyLevel.ANY,
- ConsistencyLevel.ONE,
- ConsistencyLevel.LOCAL_ONE
-]
-
-
-@requirescloudproxy
-class CloudTests(CloudProxyCluster):
- def hosts_up(self):
- return [h for h in self.cluster.metadata.all_hosts() if h.is_up]
-
- def test_resolve_and_connect(self):
- self.connect(self.creds)
-
- self.assertEqual(len(self.hosts_up()), 3)
- for host in self.cluster.metadata.all_hosts():
- self.assertTrue(host.is_up)
- self.assertIsInstance(host.endpoint, SniEndPoint)
- self.assertEqual(str(host.endpoint), "{}:{}:{}".format(
- host.endpoint.address, host.endpoint.port, host.host_id))
- self.assertIn(host.endpoint._resolved_address, ("127.0.0.1",
'::1'))
-
- def test_match_system_local(self):
- self.connect(self.creds)
-
- self.assertEqual(len(self.hosts_up()), 3)
- for host in self.cluster.metadata.all_hosts():
- row = self.session.execute('SELECT * FROM system.local',
host=host).one()
- self.assertEqual(row.host_id, host.host_id)
- self.assertEqual(row.rpc_address, host.broadcast_rpc_address)
-
- def test_set_auth_provider(self):
- self.connect(self.creds)
- self.assertIsInstance(self.cluster.auth_provider,
PlainTextAuthProvider)
- self.assertEqual(self.cluster.auth_provider.username, 'user1')
- self.assertEqual(self.cluster.auth_provider.password, 'user1')
-
- def test_support_leaving_the_auth_unset(self):
- with self.assertRaises(NoHostAvailable):
- self.connect(self.creds_no_auth)
- self.assertIsNone(self.cluster.auth_provider)
-
- def test_support_overriding_auth_provider(self):
- try:
- self.connect(self.creds,
auth_provider=PlainTextAuthProvider('invalid', 'invalid'))
- except:
- pass # this will fail soon when sni_single_endpoint is updated
- self.assertIsInstance(self.cluster.auth_provider,
PlainTextAuthProvider)
- self.assertEqual(self.cluster.auth_provider.username, 'invalid')
- self.assertEqual(self.cluster.auth_provider.password, 'invalid')
-
- def test_error_overriding_ssl_context(self):
- with self.assertRaises(ValueError) as cm:
- self.connect(self.creds, ssl_context=SSLContext(PROTOCOL_TLS))
-
- self.assertIn('cannot be specified with a cloud configuration',
str(cm.exception))
-
- def test_error_overriding_ssl_options(self):
- with self.assertRaises(ValueError) as cm:
- self.connect(self.creds, ssl_options={'check_hostname': True})
-
- self.assertIn('cannot be specified with a cloud configuration',
str(cm.exception))
-
- def _bad_hostname_metadata(self, config, http_data):
- config = parse_metadata_info(config, http_data)
- config.sni_host = "127.0.0.1"
- return config
-
- def test_verify_hostname(self):
- with patch('cassandra.datastax.cloud.parse_metadata_info',
wraps=self._bad_hostname_metadata):
- with self.assertRaises(NoHostAvailable) as e:
- self.connect(self.creds)
- self.assertIn("hostname", str(e.exception).lower())
-
- def test_error_when_bundle_doesnt_exist(self):
- try:
- self.connect('/invalid/path/file.zip')
- except Exception as e:
- self.assertIsInstance(e, FileNotFoundError)
-
- def test_load_balancing_policy_is_dcawaretokenlbp(self):
- self.connect(self.creds)
-
self.assertIsInstance(self.cluster.profile_manager.default.load_balancing_policy,
- TokenAwarePolicy)
-
self.assertIsInstance(self.cluster.profile_manager.default.load_balancing_policy._child_policy,
- DCAwareRoundRobinPolicy)
-
- def test_resolve_and_reconnect_on_node_down(self):
-
- self.connect(self.creds,
- idle_heartbeat_interval=1, idle_heartbeat_timeout=1,
- reconnection_policy=ConstantReconnectionPolicy(120))
-
- self.assertEqual(len(self.hosts_up()), 3)
- CLOUD_PROXY_SERVER.stop_node(1)
- wait_until_not_raised(
- lambda: self.assertEqual(len(self.hosts_up()), 2),
- 0.02, 250)
-
- host = [h for h in self.cluster.metadata.all_hosts() if not h.is_up][0]
- with patch.object(SniEndPoint, "resolve", wraps=host.endpoint.resolve)
as mocked_resolve:
- CLOUD_PROXY_SERVER.start_node(1)
- wait_until_not_raised(
- lambda: self.assertEqual(len(self.hosts_up()), 3),
- 0.02, 250)
- mocked_resolve.assert_called()
-
- def test_metadata_unreachable(self):
- with self.assertRaises(DriverException) as cm:
- self.connect(self.creds_unreachable, connect_timeout=1)
-
- self.assertIn('Unable to connect to the metadata service',
str(cm.exception))
-
- def test_metadata_ssl_error(self):
- with self.assertRaises(DriverException) as cm:
- self.connect(self.creds_invalid_ca)
-
- self.assertIn('Unable to connect to the metadata', str(cm.exception))
-
- def test_default_consistency(self):
- self.connect(self.creds)
- self.assertEqual(self.session.default_consistency_level,
ConsistencyLevel.LOCAL_QUORUM)
- # Verify EXEC_PROFILE_DEFAULT, EXEC_PROFILE_GRAPH_DEFAULT,
- # EXEC_PROFILE_GRAPH_SYSTEM_DEFAULT,
EXEC_PROFILE_GRAPH_ANALYTICS_DEFAULT
- for ep_key in self.cluster.profile_manager.profiles.keys():
- ep = self.cluster.profile_manager.profiles[ep_key]
- self.assertEqual(
- ep.consistency_level,
- ConsistencyLevel.LOCAL_QUORUM,
- "Expecting LOCAL QUORUM for profile {}, but got {}
instead".format(
- _execution_profile_to_string(ep_key),
ConsistencyLevel.value_to_name[ep.consistency_level]
- ))
-
- def test_default_consistency_of_execution_profiles(self):
- cloud_config = {'secure_connect_bundle': self.creds}
- self.cluster = Cluster(cloud=cloud_config, protocol_version=4,
execution_profiles={
- 'pre_create_default_ep': ExecutionProfile(),
- 'pre_create_changed_ep': ExecutionProfile(
- consistency_level=ConsistencyLevel.LOCAL_ONE,
- ),
- })
- self.cluster.add_execution_profile('pre_connect_default_ep',
ExecutionProfile())
- self.cluster.add_execution_profile(
- 'pre_connect_changed_ep',
- ExecutionProfile(
- consistency_level=ConsistencyLevel.LOCAL_ONE,
- )
- )
- session = self.cluster.connect(wait_for_all_pools=True)
-
- self.cluster.add_execution_profile('post_connect_default_ep',
ExecutionProfile())
- self.cluster.add_execution_profile(
- 'post_connect_changed_ep',
- ExecutionProfile(
- consistency_level=ConsistencyLevel.LOCAL_ONE,
- )
- )
-
- for default in ['pre_create_default_ep', 'pre_connect_default_ep',
'post_connect_default_ep']:
- cl =
self.cluster.profile_manager.profiles[default].consistency_level
- self.assertEqual(
- cl, ConsistencyLevel.LOCAL_QUORUM,
- "Expecting LOCAL QUORUM for profile {}, but got {}
instead".format(default, cl)
- )
- for changed in ['pre_create_changed_ep', 'pre_connect_changed_ep',
'post_connect_changed_ep']:
- cl =
self.cluster.profile_manager.profiles[changed].consistency_level
- self.assertEqual(
- cl, ConsistencyLevel.LOCAL_ONE,
- "Expecting LOCAL ONE for profile {}, but got {}
instead".format(default, cl)
- )
-
- def test_consistency_guardrails(self):
- self.connect(self.creds)
- self.session.execute(
- "CREATE KEYSPACE IF NOT EXISTS test_consistency_guardrails "
- "with replication={'class': 'SimpleStrategy',
'replication_factor': 1}"
- )
- self.session.execute("CREATE TABLE IF NOT EXISTS
test_consistency_guardrails.guardrails (id int primary key)")
- for consistency in DISALLOWED_CONSISTENCIES:
- statement = SimpleStatement(
- "INSERT INTO test_consistency_guardrails.guardrails (id)
values (1)",
- consistency_level=consistency
- )
- with self.assertRaises(InvalidRequest) as e:
- self.session.execute(statement)
- self.assertIn('not allowed for Write Consistency Level',
str(e.exception))
-
- # Sanity check to make sure we can do a normal insert
- statement = SimpleStatement(
- "INSERT INTO test_consistency_guardrails.guardrails (id) values
(1)",
- consistency_level=ConsistencyLevel.LOCAL_QUORUM
- )
- try:
- self.session.execute(statement)
- except InvalidRequest:
- self.fail("InvalidRequest was incorrectly raised for write query
at LOCAL QUORUM!")
-
- def test_cqlengine_can_connect(self):
- class TestModel(Model):
- id = columns.Integer(primary_key=True)
- val = columns.Text()
-
- connection.setup(None, "test", cloud={'secure_connect_bundle':
self.creds})
- create_keyspace_simple('test', 1)
- sync_table(TestModel)
- TestModel.objects.create(id=42, value='test')
- self.assertEqual(len(TestModel.objects.all()), 1)
diff --git a/tests/integration/cloud/test_cloud_schema.py
b/tests/integration/cloud/test_cloud_schema.py
deleted file mode 100644
index 8dff4950..00000000
--- a/tests/integration/cloud/test_cloud_schema.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright DataStax, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License
-"""
-This is mostly copypasta from integration/long/test_schema.py
-
-TODO: Come up with way to run cloud and local tests without duplication
-"""
-
-import logging
-import time
-
-from cassandra import ConsistencyLevel
-from cassandra.cluster import Cluster
-from cassandra.query import SimpleStatement
-
-from tests.integration import execute_until_pass
-from tests.integration.cloud import CloudProxyCluster
-
-log = logging.getLogger(__name__)
-
-
-class CloudSchemaTests(CloudProxyCluster):
- def test_recreates(self):
- """
- Basic test for repeated schema creation and use, using many different
keyspaces
- """
- self.connect(self.creds)
- session = self.session
-
- for _ in self.cluster.metadata.all_hosts():
- for keyspace_number in range(5):
- keyspace = "ks_{0}".format(keyspace_number)
-
- if keyspace in self.cluster.metadata.keyspaces.keys():
- drop = "DROP KEYSPACE {0}".format(keyspace)
- log.debug(drop)
- execute_until_pass(session, drop)
-
- create = "CREATE KEYSPACE {0} WITH replication = {{'class':
'SimpleStrategy', 'replication_factor': 3}}".format(
- keyspace)
- log.debug(create)
- execute_until_pass(session, create)
-
- create = "CREATE TABLE {0}.cf (k int PRIMARY KEY, i
int)".format(keyspace)
- log.debug(create)
- execute_until_pass(session, create)
-
- use = "USE {0}".format(keyspace)
- log.debug(use)
- execute_until_pass(session, use)
-
- insert = "INSERT INTO cf (k, i) VALUES (0, 0)"
- log.debug(insert)
- ss = SimpleStatement(insert,
consistency_level=ConsistencyLevel.QUORUM)
- execute_until_pass(session, ss)
-
- def test_for_schema_disagreement_attribute(self):
- """
- Tests to ensure that schema disagreement is properly surfaced on the
response future.
-
- Creates and destroys keyspaces/tables with various schema agreement
timeouts set.
- First part runs cql create/drop cmds with schema agreement set in such
away were it will be impossible for agreement to occur during timeout.
- It then validates that the correct value is set on the result.
- Second part ensures that when schema agreement occurs, that the result
set reflects that appropriately
-
- @since 3.1.0
- @jira_ticket PYTHON-458
- @expected_result is_schema_agreed is set appropriately on response
thefuture
-
- @test_category schema
- """
- # This should yield a schema disagreement
- cloud_config = {'secure_connect_bundle': self.creds}
- cluster = Cluster(max_schema_agreement_wait=0.001, protocol_version=4,
cloud=cloud_config)
- session = cluster.connect(wait_for_all_pools=True)
-
- rs = session.execute(
- "CREATE KEYSPACE test_schema_disagreement WITH replication =
{'class': 'SimpleStrategy', 'replication_factor': 3}")
- self.check_and_wait_for_agreement(session, rs, False)
- rs = session.execute(
- SimpleStatement("CREATE TABLE test_schema_disagreement.cf (key int
PRIMARY KEY, value int)",
- consistency_level=ConsistencyLevel.ALL))
- self.check_and_wait_for_agreement(session, rs, False)
- rs = session.execute("DROP KEYSPACE test_schema_disagreement")
- self.check_and_wait_for_agreement(session, rs, False)
- cluster.shutdown()
-
- # These should have schema agreement
- cluster = Cluster(protocol_version=4, max_schema_agreement_wait=100,
cloud=cloud_config)
- session = cluster.connect()
- rs = session.execute(
- "CREATE KEYSPACE test_schema_disagreement WITH replication =
{'class': 'SimpleStrategy', 'replication_factor': 3}")
- self.check_and_wait_for_agreement(session, rs, True)
- rs = session.execute(
- SimpleStatement("CREATE TABLE test_schema_disagreement.cf (key int
PRIMARY KEY, value int)",
- consistency_level=ConsistencyLevel.ALL))
- self.check_and_wait_for_agreement(session, rs, True)
- rs = session.execute("DROP KEYSPACE test_schema_disagreement")
- self.check_and_wait_for_agreement(session, rs, True)
- cluster.shutdown()
-
- def check_and_wait_for_agreement(self, session, rs, expected):
- # Wait for RESULT_KIND_SCHEMA_CHANGE message to arrive
- time.sleep(1)
- self.assertEqual(rs.response_future.is_schema_agreed, expected)
- if not rs.response_future.is_schema_agreed:
-
session.cluster.control_connection.wait_for_schema_agreement(wait_time=1000)
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]