diff --git a/modules/ducktests/tests/checks/utils/check_get_ssl_params_from_globals.py b/modules/ducktests/tests/checks/utils/check_get_ssl_params_from_globals.py index 63a0f38716278..4d0b7c7d866bf 100644 --- a/modules/ducktests/tests/checks/utils/check_get_ssl_params_from_globals.py +++ b/modules/ducktests/tests/checks/utils/check_get_ssl_params_from_globals.py @@ -16,17 +16,17 @@ """ Check that SslParams correctly parse SSL params from globals """ +import os import pytest from ignitetest.services.utils.ssl.ssl_params import get_ssl_params, SslParams, DEFAULT_TRUSTSTORE, \ DEFAULT_CLIENT_KEYSTORE, DEFAULT_PASSWORD, IGNITE_CLIENT_ALIAS, SSL_KEY, SSL_PARAMS_KEY, ENABLED_KEY -INSTALL_ROOT = '/opt/' -CERTIFICATE_DIR = '/opt/ignite-dev/modules/ducktests/tests/certs/' +CERT_DIR1 = "/folder1" +CERT_DIR2 = "/folder2" TEST_KEYSTORE_JKS = "client1.jks" TEST_TRUSTSTORE_JKS = "truststore.jks" TEST_PASSWORD = "qwe123" -TEST_CERTIFICATE_DIR = "/opt/certs/" def _compare(expected, actual): @@ -72,7 +72,6 @@ class TestParams: """ test_globals_jks = { - "install_root": INSTALL_ROOT, SSL_KEY: { ENABLED_KEY: True, SSL_PARAMS_KEY: { @@ -82,32 +81,28 @@ class TestParams: "trust_store_jks": TEST_TRUSTSTORE_JKS, "trust_store_password": TEST_PASSWORD}}}} test_globals_path = { - "install_root": INSTALL_ROOT, SSL_KEY: { ENABLED_KEY: True, SSL_PARAMS_KEY: { IGNITE_CLIENT_ALIAS: { - "key_store_path": TEST_CERTIFICATE_DIR + TEST_KEYSTORE_JKS, + "key_store_path": os.path.join(CERT_DIR2, TEST_KEYSTORE_JKS), "key_store_password": TEST_PASSWORD, - "trust_store_path": TEST_CERTIFICATE_DIR + TEST_TRUSTSTORE_JKS, + "trust_store_path": os.path.join(CERT_DIR2, TEST_TRUSTSTORE_JKS), "trust_store_password": TEST_PASSWORD}}}} - test_globals_default = { - "install_root": INSTALL_ROOT, - SSL_KEY: {ENABLED_KEY: True}} - test_globals_no_ssl = { - "install_root": INSTALL_ROOT} + test_globals_default = {SSL_KEY: {ENABLED_KEY: True}} + test_globals_no_ssl = {} - expected_ssl_params_jks = {'key_store_path': CERTIFICATE_DIR + TEST_KEYSTORE_JKS, + expected_ssl_params_jks = {'key_store_path': os.path.join(CERT_DIR1, TEST_KEYSTORE_JKS), 'key_store_password': TEST_PASSWORD, - 'trust_store_path': CERTIFICATE_DIR + TEST_TRUSTSTORE_JKS, + 'trust_store_path': os.path.join(CERT_DIR1, TEST_TRUSTSTORE_JKS), 'trust_store_password': TEST_PASSWORD} - expected_ssl_params_path = {'key_store_path': TEST_CERTIFICATE_DIR + TEST_KEYSTORE_JKS, + expected_ssl_params_path = {'key_store_path': os.path.join(CERT_DIR2, TEST_KEYSTORE_JKS), 'key_store_password': TEST_PASSWORD, - 'trust_store_path': TEST_CERTIFICATE_DIR + TEST_TRUSTSTORE_JKS, + 'trust_store_path': os.path.join(CERT_DIR2, TEST_TRUSTSTORE_JKS), 'trust_store_password': TEST_PASSWORD} - expected_ssl_params_default = {'key_store_path': CERTIFICATE_DIR + DEFAULT_CLIENT_KEYSTORE, + expected_ssl_params_default = {'key_store_path': os.path.join(CERT_DIR1, DEFAULT_CLIENT_KEYSTORE), 'key_store_password': DEFAULT_PASSWORD, - 'trust_store_path': CERTIFICATE_DIR + DEFAULT_TRUSTSTORE, + 'trust_store_path': os.path.join(CERT_DIR1, DEFAULT_TRUSTSTORE), 'trust_store_password': DEFAULT_PASSWORD} @@ -117,12 +112,12 @@ class CheckCaseJks: """ @staticmethod - @pytest.mark.parametrize('test_globals, expected', - [(TestParams.test_globals_jks, TestParams.expected_ssl_params_jks), - (TestParams.test_globals_path, TestParams.expected_ssl_params_path), - (TestParams.test_globals_default, TestParams.expected_ssl_params_default)]) - def check_parse(test_globals, expected): + @pytest.mark.parametrize('test_globals, shared_root, expected', + [(TestParams.test_globals_jks, CERT_DIR1, TestParams.expected_ssl_params_jks), + (TestParams.test_globals_path, CERT_DIR2, TestParams.expected_ssl_params_path), + (TestParams.test_globals_default, CERT_DIR1, TestParams.expected_ssl_params_default)]) + def check_parse(test_globals, shared_root, expected): """ Check that SslParams correctly parse SSL params from globals """ - assert _compare(expected, get_ssl_params(test_globals, IGNITE_CLIENT_ALIAS)) + assert _compare(expected, get_ssl_params(test_globals, shared_root, IGNITE_CLIENT_ALIAS)) diff --git a/modules/ducktests/tests/docker/run_tests.sh b/modules/ducktests/tests/docker/run_tests.sh index 320f992fb6372..6fb10b17622b7 100755 --- a/modules/ducktests/tests/docker/run_tests.sh +++ b/modules/ducktests/tests/docker/run_tests.sh @@ -160,7 +160,5 @@ if [[ -n "$MAX_PARALLEL" ]]; then DUCKTAPE_OPTIONS="$DUCKTAPE_OPTIONS --max-parallel $MAX_PARALLEL" fi -"$SCRIPT_DIR"/../certs/mkcerts.sh - "$SCRIPT_DIR"/ducker-ignite test "$TC_PATHS" "$DUCKTAPE_OPTIONS" \ || die "ducker-ignite test failed" diff --git a/modules/ducktests/tests/ignitetest/services/utils/control_utility.py b/modules/ducktests/tests/ignitetest/services/utils/control_utility.py index 7c3249b54c586..8d9b74d01de4d 100644 --- a/modules/ducktests/tests/ignitetest/services/utils/control_utility.py +++ b/modules/ducktests/tests/ignitetest/services/utils/control_utility.py @@ -45,7 +45,7 @@ def __init__(self, cluster, ssl_params=None, username=None, password=None): if ssl_params: self.ssl_params = ssl_params elif is_ssl_enabled(cluster.context.globals): - self.ssl_params = get_ssl_params(cluster.context.globals, IGNITE_ADMIN_ALIAS) + self.ssl_params = get_ssl_params(cluster.context.globals, cluster.shared_root, IGNITE_ADMIN_ALIAS) if username and password: self.username, self.password = username, password diff --git a/modules/ducktests/tests/ignitetest/services/utils/ignite_aware.py b/modules/ducktests/tests/ignitetest/services/utils/ignite_aware.py index 10fbf54ffdff5..936093fce5abf 100644 --- a/modules/ducktests/tests/ignitetest/services/utils/ignite_aware.py +++ b/modules/ducktests/tests/ignitetest/services/utils/ignite_aware.py @@ -106,6 +106,7 @@ def await_started(self): self.await_event("Topology snapshot", self.startup_timeout_sec, from_the_beginning=True) def start_node(self, node, **kwargs): + self.init_shared(node) self.init_persistent(node) self.__update_node_log_file(node) @@ -171,8 +172,25 @@ def init_persistent(self, node): self._prepare_configs(node) + def init_shared(self, node): + """ + Init shared directory. Content of shared directory must be equal on all test nodes. + :param node: Ignite service node. + """ + local_shared_dir = self.spec.init_local_shared() + + if not os.path.isdir(local_shared_dir): + self.logger.debug("Local shared dir not exists. Nothing to copy. " + str(local_shared_dir)) + return + + node.account.mkdirs(f"{self.persistent_root} {self.shared_root}") + + for file in os.listdir(local_shared_dir): + self.logger.debug("Copying shared file to node. " + str(file)) + node.account.copy_to(os.path.join(local_shared_dir, file), self.shared_root) + def _prepare_configs(self, node): - config = self.config.prepare_for_env(test_globals=self.globals, node=node, cluster=self) + config = self.config.prepare_for_env(self.globals, self.shared_root, node, self) for name, template in self.spec.config_templates: config_txt = template.render(config_dir=self.config_dir, work_dir=self.work_dir, config=config) diff --git a/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py index fa6efe9272b7e..544248815a9fd 100644 --- a/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py +++ b/modules/ducktests/tests/ignitetest/services/utils/ignite_configuration/__init__.py @@ -58,7 +58,7 @@ class IgniteConfiguration(NamedTuple): rebalance_batches_prefetch_count: int = None rebalance_throttle: int = None - def __prepare_ssl(self, test_globals): + def __prepare_ssl(self, test_globals, shared_root): """ Updates ssl configuration from globals. """ @@ -66,6 +66,7 @@ def __prepare_ssl(self, test_globals): if self.ssl_params is None and is_ssl_enabled(test_globals): ssl_params = get_ssl_params( test_globals, + shared_root, IGNITE_CLIENT_ALIAS if self.client_mode else IGNITE_SERVER_ALIAS ) if ssl_params: @@ -89,11 +90,11 @@ def __prepare_discovery(self, node, cluster): return config # pylint: disable=protected-access - def prepare_for_env(self, test_globals, node, cluster): + def prepare_for_env(self, test_globals, shared_root, node, cluster): """ Updates configuration based on current environment. """ - return self.__prepare_ssl(test_globals).__prepare_discovery(node, cluster) + return self.__prepare_ssl(test_globals, shared_root).__prepare_discovery(node, cluster) @property def service_type(self): @@ -118,7 +119,7 @@ class IgniteThinClientConfiguration(NamedTuple): version: IgniteVersion = DEV_BRANCH # pylint: disable=unused-argument - def prepare_for_env(self, test_globals, node, cluster): + def prepare_for_env(self, test_globals, shared_root, node, cluster): """ Updates configuration based on current environment. """ diff --git a/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py b/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py index 9731e2c2b77bf..bdc2cd419c907 100644 --- a/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py +++ b/modules/ducktests/tests/ignitetest/services/utils/ignite_spec.py @@ -21,6 +21,8 @@ import importlib import json import os +import subprocess +import tempfile from abc import ABCMeta, abstractmethod from ignitetest.services.utils import IgniteServiceType @@ -28,6 +30,7 @@ IgniteLoggerConfigTemplate, IgniteThinClientConfigTemplate from ignitetest.services.utils.jvm_utils import create_jvm_settings, merge_jvm_settings from ignitetest.services.utils.path import get_home_dir, get_module_path, IgnitePathAware +from ignitetest.services.utils.ssl.ssl_params import is_ssl_enabled from ignitetest.utils.version import DEV_BRANCH @@ -157,6 +160,31 @@ def config_file_path(self): """ return self.service.config_file + def init_local_shared(self): + """ + :return: path to local share folder. Files should be copied on all nodes in `shared_root` folder. + """ + local_dir = os.path.join(tempfile.gettempdir(), str(self.service.context.session_context.session_id)) + + if not is_ssl_enabled(self.service.context.globals) and \ + not (self.service.config.service_type == IgniteServiceType.NODE and self.service.config.ssl_params): + self.service.logger.debug("Ssl disabled. Nothing to generate.") + return local_dir + + if os.path.isdir(local_dir): + self.service.logger.debug("Local shared dir already exists. Exiting. " + local_dir) + return local_dir + + self.service.logger.debug("Local shared dir not exists. Creating. " + local_dir) + os.mkdir(local_dir) + + script_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..", "..", "certs") + + self.__runcmd(f"cp {script_dir}/*.sh {local_dir}") + self.__runcmd(f"{local_dir}/mkcerts.sh") + + return local_dir + def _jvm_opts(self): """ :return: line with extra JVM params for ignite.sh script: -J-Dparam=value -J-ea @@ -168,6 +196,14 @@ def _add_jvm_opts(self, opts): """Properly adds JVM options to current""" self.jvm_opts = merge_jvm_settings(self.jvm_opts, opts) + def __runcmd(self, cmd): + self.service.logger.debug(cmd) + proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stdout, _ = proc.communicate() + + if proc.returncode != 0: + raise RuntimeError("Command '%s' returned non-zero exit status %d: %s" % (cmd, proc.returncode, stdout)) + class IgniteNodeSpec(IgniteSpec): """ diff --git a/modules/ducktests/tests/ignitetest/services/utils/path.py b/modules/ducktests/tests/ignitetest/services/utils/path.py index 358ecfe5393f8..ed14468bbaa1e 100644 --- a/modules/ducktests/tests/ignitetest/services/utils/path.py +++ b/modules/ducktests/tests/ignitetest/services/utils/path.py @@ -104,6 +104,13 @@ def log_dir(self): """ return os.path.join(self.persistent_root, "logs") + @property + def shared_root(self): + """ + :return: path to directory with shared files - same files on all nodes + """ + return os.path.join(self.persistent_root, "shared") + @property @abstractmethod def product(self): diff --git a/modules/ducktests/tests/ignitetest/services/utils/ssl/ssl_params.py b/modules/ducktests/tests/ignitetest/services/utils/ssl/ssl_params.py index eb74b472ac20e..b3b3af1a4d595 100644 --- a/modules/ducktests/tests/ignitetest/services/utils/ssl/ssl_params.py +++ b/modules/ducktests/tests/ignitetest/services/utils/ssl/ssl_params.py @@ -27,7 +27,6 @@ DEFAULT_ADMIN_KEYSTORE = 'admin.jks' DEFAULT_PASSWORD = "123456" DEFAULT_TRUSTSTORE = "truststore.jks" -DEFAULT_ROOT = "/opt/" SSL_PARAMS_KEY = "params" SSL_KEY = "ssl" @@ -46,21 +45,19 @@ class SslParams: """ # pylint: disable=R0913 - def __init__(self, key_store_jks: str = None, key_store_password: str = DEFAULT_PASSWORD, + def __init__(self, root_dir: str, key_store_jks: str = None, key_store_password: str = DEFAULT_PASSWORD, trust_store_jks: str = DEFAULT_TRUSTSTORE, trust_store_password: str = DEFAULT_PASSWORD, - key_store_path: str = None, trust_store_path: str = None, root_dir: str = DEFAULT_ROOT): + key_store_path: str = None, trust_store_path: str = None): if not key_store_jks and not key_store_path: raise Exception("Keystore must be specified to init SslParams") - certificate_dir = os.path.join(root_dir, "ignite-dev", "modules", "ducktests", "tests", "certs") - - self.key_store_path = key_store_path if key_store_path else os.path.join(certificate_dir, key_store_jks) + self.key_store_path = key_store_path if key_store_path else os.path.join(root_dir, key_store_jks) self.key_store_password = key_store_password - self.trust_store_path = trust_store_path if trust_store_path else os.path.join(certificate_dir, trust_store_jks) + self.trust_store_path = trust_store_path if trust_store_path else os.path.join(root_dir, trust_store_jks) self.trust_store_password = trust_store_password -def get_ssl_params(_globals: dict, alias: str): +def get_ssl_params(_globals: dict, shared_root: str, alias: str): """ Gets SSL params from Globals Structure may be found in modules/ducktests/tests/checks/utils/check_get_ssl_params.py @@ -79,7 +76,6 @@ def get_ssl_params(_globals: dict, alias: str): If you specyfy ssl_params in test, you override globals """ - root_dir = _globals.get("install_root", DEFAULT_ROOT) if SSL_PARAMS_KEY in _globals[SSL_KEY] and alias in _globals[SSL_KEY][SSL_PARAMS_KEY]: ssl_param = _globals[SSL_KEY][SSL_PARAMS_KEY][alias] elif alias in default_keystore: @@ -87,7 +83,7 @@ def get_ssl_params(_globals: dict, alias: str): else: raise Exception("We don't have SSL params for: " + alias) - return SslParams(root_dir=root_dir, **ssl_param) if ssl_param else None + return SslParams(shared_root, **ssl_param) if ssl_param else None def is_ssl_enabled(_globals: dict): diff --git a/modules/ducktests/tests/ignitetest/tests/ssl_test.py b/modules/ducktests/tests/ignitetest/tests/ssl_test.py index 4dd8de012d3d2..bcdc21ec2b603 100644 --- a/modules/ducktests/tests/ignitetest/tests/ssl_test.py +++ b/modules/ducktests/tests/ignitetest/tests/ssl_test.py @@ -41,9 +41,9 @@ def test_ssl_connection(self, ignite_version): Test that IgniteService, IgniteApplicationService correctly start and stop with ssl configurations. And check ControlUtility with ssl arguments. """ - root_dir = self.test_context.globals.get("install_root", "/opt") + shared_root = "/mnt/service/shared" - server_ssl = SslParams(root_dir=root_dir, key_store_jks=DEFAULT_SERVER_KEYSTORE) + server_ssl = SslParams(shared_root, key_store_jks=DEFAULT_SERVER_KEYSTORE) server_configuration = IgniteConfiguration( version=IgniteVersion(ignite_version), ssl_params=server_ssl, @@ -54,7 +54,7 @@ def test_ssl_connection(self, ignite_version): client_configuration = server_configuration._replace( client_mode=True, - ssl_params=SslParams(root_dir=root_dir, key_store_jks=DEFAULT_CLIENT_KEYSTORE), + ssl_params=SslParams(shared_root, key_store_jks=DEFAULT_CLIENT_KEYSTORE), connector_configuration=None) app = IgniteApplicationService( @@ -63,7 +63,7 @@ def test_ssl_connection(self, ignite_version): java_class_name="org.apache.ignite.internal.ducktest.tests.smoke_test.SimpleApplication", startup_timeout_sec=180) - admin_ssl = SslParams(root_dir=root_dir, key_store_jks=DEFAULT_ADMIN_KEYSTORE) + admin_ssl = SslParams(shared_root, key_store_jks=DEFAULT_ADMIN_KEYSTORE) control_utility = ControlUtility(cluster=ignite, ssl_params=admin_ssl) ignite.start()