| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you 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. |
| */ |
| |
| #include "options.hpp" |
| #include "test_utils.hpp" |
| |
| #include "authentication_type.hpp" |
| #include "deployment_type.hpp" |
| |
| #include <algorithm> |
| #include <iostream> |
| |
| #define DEFAULT_OPTIONS_CASSSANDRA_VERSION CCM::CassVersion("3.11.6") |
| #define DEFAULT_OPTIONS_DSE_VERSION CCM::DseVersion("6.7.7") |
| #define DEFAULT_OPTIONS_DDAC_VERSION CCM::DseVersion("5.1.17") |
| |
| // Initialize the defaults for all the options |
| bool Options::is_initialized_ = false; |
| bool Options::is_help_ = false; |
| bool Options::is_keep_clusters_ = false; |
| bool Options::is_log_tests_ = true; |
| CCM::CassVersion Options::server_version_ = DEFAULT_OPTIONS_CASSSANDRA_VERSION; |
| bool Options::use_git_ = false; |
| std::string Options::branch_tag_; |
| bool Options::use_install_dir_ = false; |
| std::string Options::install_dir_; |
| std::string Options::cluster_prefix_ = "cpp-driver"; |
| std::string Options::dse_username_; |
| std::string Options::dse_password_; |
| std::string Options::host_ = "127.0.0.1"; |
| short Options::port_ = 22; |
| std::string Options::username_ = "vagrant"; |
| std::string Options::password_ = "vagrant"; |
| std::string Options::public_key_ = "public.key"; |
| std::string Options::private_key_ = "private.key"; |
| bool Options::is_verbose_ccm_ = false; |
| bool Options::is_verbose_integration_ = false; |
| |
| // Static initialization is not guaranteed for the following types |
| CCM::DseCredentialsType Options::dse_credentials_type_; |
| CCM::AuthenticationType Options::authentication_type_; |
| CCM::DeploymentType Options::deployment_type_; |
| std::set<TestCategory> Options::categories_; |
| CCM::ServerType Options::server_type_; |
| |
| bool Options::initialize(int argc, char* argv[]) { |
| // Only allow initialization to occur once |
| if (!is_initialized_) { |
| // Initialize values that may not be assigned during static initialization |
| dse_credentials_type_ = CCM::DseCredentialsType::USERNAME_PASSWORD; |
| authentication_type_ = CCM::AuthenticationType::USERNAME_PASSWORD; |
| deployment_type_ = CCM::DeploymentType::LOCAL; |
| server_type_ = CCM::ServerType::CASSANDRA; |
| |
| // Check for the help argument first (keeps defaults for help display) |
| for (int i = 1; i < argc; ++i) { |
| if (std::string(argv[i]) == "--help") { |
| print_help(); |
| is_help_ = true; |
| return false; |
| } |
| } |
| |
| // Check for the DSE argument (update default server version) |
| for (int i = 1; i < argc; ++i) { |
| if (std::string(argv[i]) == "--dse") { |
| server_version_ = DEFAULT_OPTIONS_DSE_VERSION; |
| } else if (std::string(argv[i]) == "--ddac") { |
| server_version_ = DEFAULT_OPTIONS_DDAC_VERSION; |
| } |
| } |
| |
| // Iterate through the command line arguments and parse the options |
| for (int i = 1; i < argc; ++i) { |
| std::vector<std::string> option = test::Utils::explode(argv[i], '='); |
| std::string key(test::Utils::to_lower(option[0])); |
| std::string value; |
| if (option.size() > 1) { |
| value = option[1]; |
| } |
| // Integration test options |
| if (key == "--keep-clusters") { |
| is_keep_clusters_ = true; |
| } else if (key == "--log-tests") { |
| if (!value.empty()) { |
| is_log_tests_ = bool_value(value); |
| } else { |
| std::cerr << "Missing Log Tests Boolean: Using default " << is_log_tests_ << std::endl; |
| } |
| } |
| // CCM bridge specific options |
| else if (key == "--version") { |
| if (!value.empty()) { |
| server_version_ = CCM::CassVersion(value); |
| } else { |
| std::cerr << "Missing Server Version: Using default " << server_version_.to_string() |
| << std::endl; |
| } |
| } else if (key == "--dse") { |
| server_type_ = CCM::ServerType::DSE; |
| } else if (key == "--ddac") { |
| server_type_ = CCM::ServerType::DDAC; |
| } else if (key == "--dse-username") { |
| if (!value.empty()) { |
| dse_username_ = value; |
| } |
| } else if (key == "--dse-password") { |
| if (!value.empty()) { |
| dse_password_ = value; |
| } |
| } else if (key == "--dse-credentials") { |
| CCM::DseCredentialsType type = CCM::DseCredentialsType::from_string(value); |
| if (type == CCM::DseCredentialsType::INVALID) { |
| std::cerr << "Invalid DSE/DDAC Credentials Type: Using default " |
| << dse_credentials_type_.to_string() << std::endl; |
| } else { |
| dse_credentials_type_ = type; |
| } |
| } else if (key == "--git") { |
| use_git_ = true; |
| if (!value.empty()) { |
| branch_tag_ = value; |
| } |
| } else if (key == "--install-dir") { |
| use_install_dir_ = true; |
| if (value.empty()) { |
| std::cerr << "Disabling the Use of the Installation Directory: Installation directory " |
| "must not be empty" |
| << std::endl; |
| use_install_dir_ = false; |
| } else { |
| install_dir_ = value; |
| } |
| } else if (key == "--prefix") { |
| if (!value.empty()) { |
| cluster_prefix_ = value; |
| } else { |
| std::cerr << "Missing Cluster Prefix: Using default " << cluster_prefix_ << std::endl; |
| } |
| } else if (key == "--category") { |
| if (!value.empty()) { |
| std::vector<std::string> categories = test::Utils::explode(value, ':'); |
| for (std::vector<std::string>::iterator iterator = categories.begin(); |
| iterator != categories.end(); ++iterator) { |
| try { |
| categories_.insert(*iterator); |
| } catch (TestCategory::Exception& tce) { |
| std::cerr << "Invalid Category: " << *iterator << " will be ignored" |
| << " (" << tce.what() << ")" << std::endl; |
| } |
| } |
| } else { |
| std::cerr << "Missing Category: All applicable tests will run" << std::endl; |
| } |
| } else if (key == "--verbose") { |
| if (!value.empty() && !bool_value(value)) { |
| std::vector<std::string> components = test::Utils::explode(value, ','); |
| for (std::vector<std::string>::iterator it = components.begin(), end = components.end(); |
| it != end; ++it) { |
| std::string component = test::Utils::to_lower(*it); |
| if (component == "ccm") { |
| is_verbose_ccm_ = true; |
| } else if (component == "integration") { |
| is_verbose_integration_ = true; |
| } else { |
| std::cerr << "Invalid Component \"" << *it |
| << "\": Available components are [ccm, integration]" << std::endl; |
| } |
| } |
| } else { |
| is_verbose_ccm_ = true; |
| is_verbose_integration_ = true; |
| } |
| } |
| #ifdef CASS_USE_LIBSSH2 |
| else if (key == "--authentication") { |
| CCM::AuthenticationType type = CCM::AuthenticationType::from_string(value); |
| if (type == CCM::AuthenticationType::INVALID) { |
| std::cerr << "Invalid Authentication Type: Using default " |
| << authentication_type_.to_string() << std::endl; |
| } else { |
| authentication_type_ = type; |
| } |
| } else if (key == "--deployment") { |
| CCM::DeploymentType type = CCM::DeploymentType::from_string(value); |
| if (type == CCM::DeploymentType::INVALID) { |
| std::cerr << "Invalid Deployment Type: Using default " << deployment_type_.to_string() |
| << std::endl; |
| } else { |
| deployment_type_ = type; |
| } |
| } else if (key == "--host") { |
| if (!value.empty()) { |
| host_ = value; |
| } else { |
| std::cerr << "Missing Host: Using default " << host_ << std::endl; |
| } |
| } else if (key == "--port") { |
| // Convert the value |
| if (!value.empty()) { |
| std::stringstream ss(value); |
| if (!(ss >> port_).fail()) { |
| continue; |
| } else { |
| std::cerr << "Invalid Port: Using default [" << port_ << "]"; |
| } |
| } |
| } else if (key == "--username") { |
| if (!value.empty()) { |
| username_ = value; |
| } else { |
| std::cerr << "Missing Username: Using default " << username_ << std::endl; |
| } |
| } else if (key == "--password") { |
| if (!value.empty()) { |
| password_ = value; |
| } else { |
| std::cerr << "Missing Password: Using default " << password_ << std::endl; |
| } |
| } else if (key == "--public-key") { |
| if (!value.empty()) { |
| public_key_ = value; |
| } else { |
| std::cerr << "Missing Public Key Filename: Using default " << public_key_ << std::endl; |
| } |
| } else if (key == "--private-key") { |
| if (!value.empty()) { |
| private_key_ = value; |
| } else { |
| std::cerr << "Missing Private Key Filename: Using default " << private_key_ << std::endl; |
| } |
| } |
| #endif |
| } |
| |
| // Determine if the options should have their defaults reset |
| if (categories_.empty()) { |
| for (TestCategory::iterator iterator = TestCategory::begin(); iterator != TestCategory::end(); |
| ++iterator) { |
| // Only add the DSE test category if DSE is enabled |
| if (*iterator != TestCategory::DSE || is_dse()) { |
| categories_.insert(*iterator); |
| } else { |
| std::cerr << "DSE Category Will be Ignored: DSE is not enabled [--dse]" << std::endl; |
| } |
| } |
| } |
| if (deployment_type_ == CCM::DeploymentType::LOCAL) { |
| host_ = "127.0.0.1"; |
| } |
| if (!is_cassandra() && !use_install_dir_) { |
| // Determine if the DSE/DDAC credentials type should be updated |
| if (dse_credentials_type_ == CCM::DseCredentialsType::USERNAME_PASSWORD) { |
| if (dse_username_.empty() || dse_password_.empty()) { |
| std::cerr << "Invalid Username and/or Password: Default to INI_FILE DSE/DDAC credentials" |
| << std::endl; |
| dse_credentials_type_ = CCM::DseCredentialsType::INI_FILE; |
| } |
| } |
| } |
| |
| is_initialized_ = true; |
| } |
| |
| // Indicate the arguments were parsed successfully |
| return true; |
| } |
| |
| void Options::print_help() { |
| std::cout << std::endl << "Integration Test Options:" << std::endl; |
| std::cout << " --log-tests=(yes|no)" << std::endl |
| << " " |
| << "Enable/Disable logging of driver messages per test to a file." << std::endl |
| << " The default is " << (log_tests() ? "yes" : "no") << "." << std::endl; |
| std::cout << std::endl << "CCM Options:" << std::endl; |
| std::cout << " --version=[VERSION]" << std::endl |
| << " " |
| << "Cassandra/DSE/DDAC version to use." << std::endl |
| << " Default:" << std::endl |
| << " Cassandra Version: " << server_version().to_string() << std::endl |
| << " DSE Version: " << DEFAULT_OPTIONS_DSE_VERSION.to_string() << std::endl |
| << " DDAC Version: " << DEFAULT_OPTIONS_DDAC_VERSION.to_string() << std::endl; |
| std::string categories; |
| for (TestCategory::iterator iterator = TestCategory::begin(); iterator != TestCategory::end(); |
| ++iterator) { |
| if (iterator != TestCategory::begin()) { |
| categories += "|"; |
| } |
| categories += iterator->name(); |
| } |
| std::cout << " --category=[" << categories << "]" << std::endl |
| << " " |
| << "Run only the categories whose name matches one of the available" << std::endl |
| << " categories; ':' separates two categories. The default is all categories" |
| << std::endl |
| << " being executed." << std::endl; |
| std::cout << " --dse" << std::endl |
| << " " |
| << "Indicate server version supplied is DSE." << std::endl; |
| std::cout << " --ddac" << std::endl |
| << " " |
| << "Indicate server version supplied is DDAC." << std::endl; |
| std::cout << " --dse-credentials=(USERNAME_PASSWORD|INI_FILE)" << std::endl |
| << " " |
| << "DSE/DDAC credentials to use for download authentication. The default is " |
| << std::endl |
| << " " << dse_credentials().to_string() << "." << std::endl; |
| std::cout << " --dse-username=[USERNAME]" << std::endl |
| << " " |
| << "Username to use for DSE/DDAC download authentication." << std::endl; |
| std::cout << " --dse-password=[PASSWORD]" << std::endl |
| << " " |
| << "Password to use for DSE/DDAC download authentication." << std::endl; |
| std::cout << " --git" << std::endl |
| << " " |
| << "Indicate Cassandra/DSE server download should be obtained from" << std::endl |
| << " ASF/GitHub." << std::endl; |
| std::cout << " --git=[BRANCH_OR_TAG]" << std::endl |
| << " " |
| << "Indicate Cassandra/DSE server branch/tag should be obtained from" << std::endl |
| << " ASF/GitHub." << std::endl; |
| std::cout << " --install-dir=[INSTALL_DIR]" << std::endl |
| << " " |
| << "Indicate Cassandra/DSE installation directory to use." << std::endl; |
| std::cout << " --prefix=[PREFIX]" << std::endl |
| << " " |
| << "CCM cluster prefix. The default is " << cluster_prefix() << "." << std::endl; |
| #ifdef CASS_USE_LIBSSH2 |
| std::cout << " --authentication=(USERNAME_PASSWORD|PUBLIC_KEY)" << std::endl |
| << " " |
| << "Authentication to use for remote deployment. The default is" << std::endl |
| << " " << authentication_type().to_string() << "." << std::endl; |
| std::cout << " --deployment=(LOCAL|REMOTE)" << std::endl |
| << " " |
| << "Deployment to use. The default is " << deployment_type().to_string() << "." |
| << std::endl; |
| std::cout << " --host=[IP_ADDRESS]" << std::endl |
| << " " |
| << "IP address to use for remote deployment. The default is " << host() << "." |
| << std::endl; |
| std::cout << " --port=[PORT]" << std::endl |
| << " " |
| << "Port to use for remote deployment. The default is " << port() << "." << std::endl; |
| std::cout << " --username=[USERNAME]" << std::endl |
| << " " |
| << "Username to use for remote deployment. The default is " << username() << "." |
| << std::endl; |
| std::cout << " --password=[PASSWORD]" << std::endl |
| << " " |
| << "Password to use for remote deployment. The default is " << password() << "." |
| << std::endl; |
| std::cout << " --public-key=[FILENAME]" << std::endl |
| << " " |
| << "Public key filename to use for remote deployment. The default is" << std::endl |
| << " " << public_key() << "." << std::endl; |
| std::cout << " --private-key=[FILENAME]" << std::endl |
| << " " |
| << "Private key filename to use for remote deployment. The default is" << std::endl |
| << " " << private_key() << "." << std::endl; |
| #endif |
| std::cout << " --keep-clusters" << std::endl |
| << " " |
| << "Indicate CCM clusters should not be removed after tests terminate." << std::endl; |
| std::cout << " --verbose(=ccm,integration)" << std::endl |
| << " " |
| << "Enable verbose output for component(s)." << std::endl; |
| std::cout << std::endl; |
| } |
| |
| void Options::print_settings() { |
| if (keep_clusters()) { |
| std::cout << " Keep clusters" << std::endl; |
| } |
| if (log_tests()) { |
| std::cout << " Logging driver messages" << std::endl; |
| } |
| if (!is_cassandra()) { |
| std::cout << " " << server_type_.to_string() |
| << " Version: " << CCM::DseVersion(server_version()).to_string() << std::endl; |
| if (!use_install_dir()) { |
| if (dse_credentials() == CCM::DseCredentialsType::USERNAME_PASSWORD) { |
| std::cout << " Username: " << dse_username() << std::endl; |
| std::cout << " Password: " << dse_password() << std::endl; |
| } else { |
| std::cout << " Using INI file for DSE/DDAC download authentication" << std::endl; |
| } |
| } |
| } else { |
| std::cout << " " << server_type_.to_string() << " Version: " << server_version().to_string() |
| << std::endl; |
| } |
| if (use_install_dir()) { |
| std::cout << " Using installation directory [" << install_dir() << "]" << std::endl; |
| } else { |
| if (use_git()) { |
| std::cout << " Using " << (is_dse() ? "GitHub" : "ASF") << " repository" << std::endl; |
| if (!branch_tag_.empty()) { |
| std::cout << " Using branch/tag: " << branch_tag_ << std::endl; |
| } |
| } |
| } |
| std::cout << " CCM Cluster Prefix: " << cluster_prefix() << std::endl; |
| #ifdef CASS_USE_LIBSSH2 |
| if (deployment_type() == CCM::DeploymentType::REMOTE) { |
| std::cout << " Remote Deployment:" << std::endl; |
| std::cout << " Host: " << host() << std::endl; |
| std::cout << " Port: " << port() << std::endl; |
| if (authentication_type() == CCM::AuthenticationType::USERNAME_PASSWORD) { |
| std::cout << " Username: " << username() << std::endl; |
| std::cout << " Password: " << password() << std::endl; |
| } else { |
| std::cout << " Public Key Filename: " << public_key() << std::endl; |
| std::cout << " Private Key Filename: " << private_key() << std::endl; |
| } |
| } |
| #endif |
| } |
| |
| bool Options::is_help() { return is_help_; } |
| |
| bool Options::keep_clusters() { return is_keep_clusters_; } |
| |
| bool Options::log_tests() { return is_log_tests_; } |
| |
| CCM::CassVersion Options::server_version() { return server_version_; } |
| |
| CCM::ServerType Options::server_type() { return server_type_; } |
| |
| bool Options::is_cassandra() { return server_type_ == CCM::ServerType::CASSANDRA; } |
| |
| bool Options::is_dse() { return server_type_ == CCM::ServerType::DSE; } |
| |
| bool Options::is_ddac() { return server_type_ == CCM::ServerType::DDAC; } |
| |
| CCM::DseCredentialsType Options::dse_credentials() { |
| // Static initialization cannot be guaranteed |
| if (!is_initialized_) { |
| return CCM::DseCredentialsType::USERNAME_PASSWORD; |
| } |
| return dse_credentials_type_; |
| } |
| |
| const std::string& Options::dse_username() { return dse_username_; } |
| |
| const std::string& Options::dse_password() { return dse_password_; } |
| |
| bool Options::use_git() { return use_git_; } |
| |
| const std::string& Options::branch_tag() { return branch_tag_; } |
| |
| bool Options::use_install_dir() { return use_install_dir_; } |
| |
| const std::string& Options::install_dir() { return install_dir_; } |
| |
| const std::string& Options::cluster_prefix() { return cluster_prefix_; } |
| |
| CCM::DeploymentType Options::deployment_type() { |
| // Static initialization cannot be guaranteed |
| if (!is_initialized_) { |
| return CCM::DeploymentType::LOCAL; |
| } |
| return deployment_type_; |
| } |
| |
| CCM::AuthenticationType Options::authentication_type() { |
| // Static initialization cannot be guaranteed |
| if (!is_initialized_) { |
| return CCM::AuthenticationType::USERNAME_PASSWORD; |
| } |
| return authentication_type_; |
| } |
| |
| std::set<TestCategory> Options::categories() { return categories_; } |
| |
| const std::string& Options::host() { return host_; } |
| |
| std::string Options::host_prefix() { return host_.substr(0, host_.size() - 1); } |
| |
| short Options::port() { return port_; } |
| |
| const std::string& Options::username() { return username_; } |
| |
| const std::string& Options::password() { return password_; } |
| |
| const std::string& Options::public_key() { return public_key_; } |
| |
| const std::string& Options::private_key() { return private_key_; } |
| |
| SharedPtr<CCM::Bridge, StdDeleter<CCM::Bridge> > Options::ccm() { |
| return new CCM::Bridge(Options::server_version(), Options::use_git(), Options::branch_tag(), |
| Options::use_install_dir(), Options::install_dir(), Options::server_type(), |
| CCM::Bridge::DEFAULT_DSE_WORKLOAD, Options::cluster_prefix(), |
| Options::dse_credentials(), Options::dse_username(), |
| Options::dse_password(), Options::deployment_type(), |
| Options::authentication_type(), Options::host(), Options::port(), |
| Options::username(), Options::password(), Options::public_key(), |
| Options::private_key(), Options::is_verbose_ccm()); |
| } |
| |
| bool Options::is_verbose_ccm() { return is_verbose_ccm_; } |
| |
| bool Options::is_verbose_integration() { return is_verbose_integration_; } |
| |
| Options::Options() {} |
| |
| bool Options::bool_value(const std::string& value) { |
| std::string lower_value = test::Utils::to_lower(value); |
| if (lower_value == "yes" || lower_value == "true" || lower_value == "on" || lower_value == "0") { |
| return true; |
| } |
| return false; |
| } |