You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-10-30 07:25:34 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			185 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import json
 | |
| import subprocess
 | |
| from pathlib import Path
 | |
| 
 | |
| import pytest
 | |
| 
 | |
| from integration_tests import cluster_mgmt
 | |
| from integration_tests.ssh import ClusterConfig, RemoteHost, run_on_all_hosts_parallel
 | |
| from integration_tests.state import activate_single_node_config
 | |
| from integration_tests.utils import change_directory
 | |
| 
 | |
| 
 | |
| def pytest_addoption(parser):
 | |
|     """Add terraform directory option to pytest command line arguments."""
 | |
|     parser.addoption(
 | |
|         "--terraform-dir",
 | |
|         action="store",
 | |
|         default=None,
 | |
|         required=True,
 | |
|         help="Directory where terraform was run to set up the test cluster",
 | |
|     )
 | |
|     parser.addoption(
 | |
|         "--create-cluster",
 | |
|         action="store_true",
 | |
|         default=False,
 | |
|         help="Create the cluster before running tests",
 | |
|     )
 | |
|     parser.addoption(
 | |
|         "--destroy-cluster",
 | |
|         action="store_true",
 | |
|         default=False,
 | |
|         help="Destroy the cluster after running tests",
 | |
|     )
 | |
|     parser.addoption(
 | |
|         "--ssh-user",
 | |
|         default="ubuntu",
 | |
|         help="SSH user to connect to the cluster hosts",
 | |
|     )
 | |
| 
 | |
| 
 | |
| @pytest.fixture(scope="session")
 | |
| def terraform_dir(request) -> Path:
 | |
|     """
 | |
|     Fixture to provide the terraform directory path.
 | |
|     Fails explicitly if --terraform-dir option is not provided.
 | |
|     """
 | |
|     terraform_directory = request.config.getoption("--terraform-dir")
 | |
|     if not terraform_directory:
 | |
|         pytest.fail("--terraform-dir option is required but not provided")
 | |
|     terraform_directory = Path(terraform_directory).resolve()
 | |
|     if not terraform_directory.is_dir():
 | |
|         pytest.fail(f"Specified terraform directory '{terraform_directory}' does not exist")
 | |
|     return terraform_directory
 | |
| 
 | |
| 
 | |
| @pytest.fixture(scope="session")
 | |
| def prepared_cluster(request, terraform_dir):
 | |
|     """
 | |
|     Provides existence of the cluster
 | |
|     If it doesn't exist and --create-cluster is passed, it creates it.
 | |
|     If it exists and --create-cluster is passed, it re-creates it.
 | |
|     If --destroy-cluster is passed, it destroys the cluster when the tests finish.
 | |
|     """
 | |
|     create_cluster = request.config.getoption("--create-cluster")
 | |
|     destroy_cluster = request.config.getoption("--destroy-cluster")
 | |
| 
 | |
|     cluster_already_exists = cluster_mgmt.cluster_exists(terraform_dir)
 | |
| 
 | |
|     if create_cluster:
 | |
|         if cluster_already_exists:
 | |
|             print("Cluster already exists, destroying it first...")
 | |
|             cluster_mgmt.destroy_cluster(terraform_dir)
 | |
|         print("Creating the cluster...")
 | |
|         cluster_mgmt.create_cluster(terraform_dir)
 | |
| 
 | |
|     yield
 | |
| 
 | |
|     if destroy_cluster:
 | |
|         print("Destroying the cluster...")
 | |
|         cluster_mgmt.destroy_cluster(terraform_dir)
 | |
| 
 | |
| 
 | |
| @pytest.fixture(scope="session")
 | |
| def cluster_config(request, terraform_dir, prepared_cluster) -> ClusterConfig:
 | |
|     """
 | |
|     Fixture to provide the cluster configuration.
 | |
|     """
 | |
|     with change_directory(terraform_dir):
 | |
|         # Read the cluster configuration from the terraform output
 | |
|         outputs = json.loads(subprocess.check_output(
 | |
|             ["terraform", "output", "-json"],
 | |
|             text=True,
 | |
|         ))
 | |
| 
 | |
|         if outputs == {}:
 | |
|             pytest.fail("Terraform output is empty, looks like cluster is not yet created. Pass --create-cluster option to create it.")
 | |
| 
 | |
|         key_file_path = Path(outputs["ssh_key_file"]["value"])
 | |
|         ssh_user = request.config.getoption("--ssh-user")
 | |
| 
 | |
|         mcs_nodes = []
 | |
|         for host_descr in outputs["columnstore_nodes"]["value"]:
 | |
|             mcs_nodes.append(
 | |
|                 RemoteHost(
 | |
|                     name=host_descr["name"],
 | |
|                     private_ip=host_descr["private_ip"],
 | |
|                     public_fqdn=host_descr["public_dns"],
 | |
|                     key_file_path=key_file_path,
 | |
|                     ssh_user=ssh_user,
 | |
|                 )
 | |
|             )
 | |
| 
 | |
|         maxscale_nodes = []
 | |
|         for host_descr in outputs["maxscale_nodes"]["value"]:
 | |
|             maxscale_nodes.append(
 | |
|                 RemoteHost(
 | |
|                     name=host_descr["name"],
 | |
|                     private_ip=host_descr["private_ip"],
 | |
|                     public_fqdn=host_descr["public_dns"],
 | |
|                     key_file_path=key_file_path,
 | |
|                     ssh_user=ssh_user,
 | |
|                 )
 | |
|             )
 | |
| 
 | |
|         all_hosts = mcs_nodes + maxscale_nodes
 | |
|         # Check if all hosts are reachable
 | |
|         for host in all_hosts:
 | |
|             if not host.is_reachable():
 | |
|                 pytest.fail(f"Host {host.name} is not reachable via SSH")
 | |
| 
 | |
|         cluster_config = ClusterConfig(mcs_hosts=mcs_nodes, maxscale_hosts=maxscale_nodes)
 | |
|         return cluster_config
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def disconnected_cluster(cluster_config):
 | |
|     """
 | |
|     Fixture to activate single node configuration on all hosts in the cluster,
 | |
|       none of the nodes are in the cluster.
 | |
|     """
 | |
|     print("Activating single node configuration on all hosts...")
 | |
|     run_on_all_hosts_parallel(cluster_config.mcs_hosts, activate_single_node_config)
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def only_primary_in_cluster(disconnected_cluster, cluster_config):
 | |
|     """
 | |
|     Fixture that provides a cluster with only the primary node added
 | |
|     """
 | |
|     print("Adding only primary node to the cluster...")
 | |
|     cmd = f"cluster node add --node {cluster_config.primary.private_ip}"
 | |
|     cluster_config.primary.exec_mcs(cmd)
 | |
| 
 | |
|     status_out = cluster_config.primary.exec_mcs("cluster status")
 | |
|     assert status_out["num_nodes"] == 1
 | |
|     assert str(cluster_config.primary.private_ip) in status_out
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def only_primary_and_one_replica_in_cluster(only_primary_in_cluster, cluster_config):
 | |
|     """
 | |
|     Fixture that provides a cluster with only the primary and one replica node added
 | |
|     """
 | |
|     print("Adding one replica...")
 | |
|     cmd = f"cluster node add --node {cluster_config.replicas[0].private_ip}"
 | |
|     cluster_config.primary.exec_mcs(cmd)
 | |
| 
 | |
|     status_out = cluster_config.primary.exec_mcs("cluster status")
 | |
|     assert status_out["num_nodes"] == 2
 | |
| 
 | |
| 
 | |
| @pytest.fixture
 | |
| def complete_cluster(cluster_config, disconnected_cluster, only_primary_in_cluster):
 | |
|     """
 | |
|     Fixture to activate multinode configuration on all hosts in the cluster.
 | |
|     """
 | |
|     print("Adding replicas to the cluster...")
 | |
|     cmd = "cluster node add "
 | |
|     for host in cluster_config.replicas:
 | |
|         cmd += f"--node {host.private_ip} "
 | |
|     cluster_config.primary.exec_mcs(cmd)
 | |
| 
 | |
|     status_out = cluster_config.primary.exec_mcs("cluster status")
 | |
|     assert status_out["num_nodes"] == len(cluster_config.mcs_hosts)
 |