From d74f1357d48c82333dfa063bf9db4c75855ae4fb Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Thu, 28 May 2020 01:06:33 +0400 Subject: [PATCH 001/143] Add LDAP authentication support --- programs/server/MySQLHandler.cpp | 2 +- programs/server/users.xml | 35 +++ src/Access/AccessControlManager.cpp | 119 ++++++++++ src/Access/AccessControlManager.h | 4 + src/Access/Authentication.cpp | 25 ++- src/Access/Authentication.h | 20 +- src/Access/ContextAccess.cpp | 4 +- src/Access/ContextAccess.h | 4 +- src/Access/ExternalAuthenticators.cpp | 28 +++ src/Access/ExternalAuthenticators.h | 24 ++ src/Access/LDAPClient.cpp | 279 ++++++++++++++++++++++++ src/Access/LDAPClient.h | 55 +++++ src/Access/LDAPParams.h | 63 ++++++ src/Access/UsersConfigAccessStorage.cpp | 20 +- src/Access/ya.make | 2 + src/Common/ErrorCodes.cpp | 1 + src/Core/config_core.h.in | 1 + src/Interpreters/Context.cpp | 2 +- src/Parsers/ASTCreateUserQuery.cpp | 4 + src/Parsers/ASTCreateUserQuery.h | 4 +- src/Parsers/ParserCreateUserQuery.cpp | 11 + src/Parsers/ParserCreateUserQuery.h | 4 +- 22 files changed, 696 insertions(+), 15 deletions(-) create mode 100644 src/Access/ExternalAuthenticators.cpp create mode 100644 src/Access/ExternalAuthenticators.h create mode 100644 src/Access/LDAPClient.cpp create mode 100644 src/Access/LDAPClient.h create mode 100644 src/Access/LDAPParams.h diff --git a/programs/server/MySQLHandler.cpp b/programs/server/MySQLHandler.cpp index a3ac3601e01..afad1a99817 100644 --- a/programs/server/MySQLHandler.cpp +++ b/programs/server/MySQLHandler.cpp @@ -224,7 +224,7 @@ void MySQLHandler::authenticate(const String & user_name, const String & auth_pl // For compatibility with JavaScript MySQL client, Native41 authentication plugin is used when possible (if password is specified using double SHA1). Otherwise SHA256 plugin is used. auto user = connection_context.getAccessControlManager().read(user_name); const DB::Authentication::Type user_auth_type = user->authentication.getType(); - if (user_auth_type != DB::Authentication::DOUBLE_SHA1_PASSWORD && user_auth_type != DB::Authentication::PLAINTEXT_PASSWORD && user_auth_type != DB::Authentication::NO_PASSWORD) + if (user_auth_type != DB::Authentication::LDAP_PASSWORD && user_auth_type != DB::Authentication::DOUBLE_SHA1_PASSWORD && user_auth_type != DB::Authentication::PLAINTEXT_PASSWORD && user_auth_type != DB::Authentication::NO_PASSWORD) { authPluginSSL(); } diff --git a/programs/server/users.xml b/programs/server/users.xml index 3d95269190b..286c065722e 100644 --- a/programs/server/users.xml +++ b/programs/server/users.xml @@ -27,6 +27,38 @@ + + + + + @@ -44,6 +76,9 @@ If you want to specify double SHA1, place it in 'password_double_sha1_hex' element. Example: e395796d6546b1b65db9d665cd43f0e858dd4303 + If you want to specify a previously defined LDAP server (see 'ldap_servers' above) for authentication, place its name in 'server' element inside 'ldap' element. + Example: my_ldap_server + How to generate decent password: Execute: PASSWORD=$(base64 < /dev/urandom | head -c8); echo "$PASSWORD"; echo -n "$PASSWORD" | sha256sum | tr -d '-' In first line will be password and in second - corresponding SHA256. diff --git a/src/Access/AccessControlManager.cpp b/src/Access/AccessControlManager.cpp index 1c1215a0e28..fc659d8bacb 100644 --- a/src/Access/AccessControlManager.cpp +++ b/src/Access/AccessControlManager.cpp @@ -9,13 +9,22 @@ #include #include #include +#include #include #include +#include +#include #include namespace DB { + +namespace ErrorCodes +{ + extern const int BAD_ARGUMENTS; +} + namespace { std::vector> createStorages() @@ -32,6 +41,110 @@ namespace constexpr size_t DISK_ACCESS_STORAGE_INDEX = 0; constexpr size_t USERS_CONFIG_ACCESS_STORAGE_INDEX = 1; + + auto parseLDAPServer(const Poco::Util::AbstractConfiguration & config, const String & ldap_server_name) + { + LDAPServerParams params; + + const String ldap_server_config = "ldap_servers." + ldap_server_name; + + const bool has_host = config.has(ldap_server_config + ".host"); + const bool has_port = config.has(ldap_server_config + ".port"); + const bool has_auth_dn_prefix = config.has(ldap_server_config + ".auth_dn_prefix"); + const bool has_auth_dn_suffix = config.has(ldap_server_config + ".auth_dn_suffix"); + const bool has_enable_tls = config.has(ldap_server_config + ".enable_tls"); + const bool has_tls_cert_verify = config.has(ldap_server_config + ".tls_cert_verify"); + const bool has_ca_cert_dir = config.has(ldap_server_config + ".ca_cert_dir"); + const bool has_ca_cert_file = config.has(ldap_server_config + ".ca_cert_file"); + + if (!has_host) + throw Exception("Missing 'host' entry", ErrorCodes::BAD_ARGUMENTS); + + params.host = config.getString(ldap_server_config + ".host"); + + if (params.host.empty()) + throw Exception("Empty 'host' entry", ErrorCodes::BAD_ARGUMENTS); + + if (has_auth_dn_prefix) + params.auth_dn_prefix = config.getString(ldap_server_config + ".auth_dn_prefix"); + + if (has_auth_dn_suffix) + params.auth_dn_suffix = config.getString(ldap_server_config + ".auth_dn_suffix"); + + if (has_enable_tls) + { + String enable_tls_lc_str = config.getString(ldap_server_config + ".enable_tls"); + boost::to_lower(enable_tls_lc_str); + + if (enable_tls_lc_str == "starttls") + params.enable_tls = LDAPServerParams::TLSEnable::YES_STARTTLS; + else if (config.getBool(ldap_server_config + ".enable_tls")) + params.enable_tls = LDAPServerParams::TLSEnable::YES; + else + params.enable_tls = LDAPServerParams::TLSEnable::NO; + } + + if (has_tls_cert_verify) + { + String tls_cert_verify_lc_str = config.getString(ldap_server_config + ".tls_cert_verify"); + boost::to_lower(tls_cert_verify_lc_str); + + if (tls_cert_verify_lc_str == "never") + params.tls_cert_verify = LDAPServerParams::TLSCertVerify::NEVER; + else if (tls_cert_verify_lc_str == "allow") + params.tls_cert_verify = LDAPServerParams::TLSCertVerify::ALLOW; + else if (tls_cert_verify_lc_str == "try") + params.tls_cert_verify = LDAPServerParams::TLSCertVerify::TRY; + else if (tls_cert_verify_lc_str == "demand") + params.tls_cert_verify = LDAPServerParams::TLSCertVerify::DEMAND; + else + throw Exception("Bad value for 'tls_cert_verify' entry, allowed values are: 'never', 'allow', 'try', 'demand'", ErrorCodes::BAD_ARGUMENTS); + } + + if (has_ca_cert_dir) + params.ca_cert_dir = config.getString(ldap_server_config + ".ca_cert_dir"); + + if (has_ca_cert_file) + params.ca_cert_file = config.getString(ldap_server_config + ".ca_cert_file"); + + if (has_port) + { + const auto port = config.getInt64(ldap_server_config + ".port"); + if (port < 0 || port > 65535) + throw Exception("Bad value for 'port' entry", ErrorCodes::BAD_ARGUMENTS); + + params.port = port; + } + else + params.port = (params.enable_tls == LDAPServerParams::TLSEnable::YES ? 636 : 389); + + return params; + } + + void parseAndAddLDAPServers(ExternalAuthenticators & external_authenticators, const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) + { + Poco::Util::AbstractConfiguration::Keys ldap_server_names; + config.keys("ldap_servers", ldap_server_names); + + for (const auto & ldap_server_name : ldap_server_names) + { + try + { + external_authenticators.setLDAPServerParams(ldap_server_name, parseLDAPServer(config, ldap_server_name)); + } + catch (...) + { + tryLogCurrentException(log, "Could not parse LDAP server " + backQuote(ldap_server_name)); + } + } + } + + auto parseExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) + { + auto external_authenticators = std::make_unique(); + parseAndAddLDAPServers(*external_authenticators, config, log); + return external_authenticators; + } } @@ -100,6 +213,7 @@ void AccessControlManager::setLocalDirectory(const String & directory_path) void AccessControlManager::setUsersConfig(const Poco::Util::AbstractConfiguration & users_config) { + external_authenticators = parseExternalAuthenticators(users_config, getLogger()); auto & users_config_access_storage = dynamic_cast(getStorageByIndex(USERS_CONFIG_ACCESS_STORAGE_INDEX)); users_config_access_storage.setConfiguration(users_config); } @@ -164,4 +278,9 @@ std::shared_ptr AccessControlManager::getProfileSettings( return settings_profiles_cache->getProfileSettings(profile_name); } +const ExternalAuthenticators & AccessControlManager::getExternalAuthenticators() const +{ + return *external_authenticators; +} + } diff --git a/src/Access/AccessControlManager.h b/src/Access/AccessControlManager.h index 6bcf8d7c504..4ef971dca65 100644 --- a/src/Access/AccessControlManager.h +++ b/src/Access/AccessControlManager.h @@ -36,6 +36,7 @@ class EnabledSettings; class SettingsProfilesCache; class SettingsProfileElements; class ClientInfo; +class ExternalAuthenticators; struct Settings; @@ -82,6 +83,8 @@ public: std::shared_ptr getProfileSettings(const String & profile_name) const; + const ExternalAuthenticators & getExternalAuthenticators() const; + private: class ContextAccessCache; std::unique_ptr context_access_cache; @@ -89,6 +92,7 @@ private: std::unique_ptr row_policy_cache; std::unique_ptr quota_cache; std::unique_ptr settings_profiles_cache; + std::unique_ptr external_authenticators; }; } diff --git a/src/Access/Authentication.cpp b/src/Access/Authentication.cpp index f435d6e6336..e7e8b10aabc 100644 --- a/src/Access/Authentication.cpp +++ b/src/Access/Authentication.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include #include @@ -11,6 +13,15 @@ namespace ErrorCodes extern const int BAD_ARGUMENTS; } +const String & Authentication::getLDAPServerName() const +{ + return ldap_server_name; +} + +void Authentication::setLDAPServerName(const String & server_name) +{ + ldap_server_name = server_name; +} Authentication::Digest Authentication::getPasswordDoubleSHA1() const { @@ -36,12 +47,15 @@ Authentication::Digest Authentication::getPasswordDoubleSHA1() const case DOUBLE_SHA1_PASSWORD: return password_hash; + + case LDAP_PASSWORD: + throw Exception("Cannot get password double SHA1 for user with 'LDAP_PASSWORD' authentication.", ErrorCodes::BAD_ARGUMENTS); } throw Exception("Unknown authentication type: " + std::to_string(static_cast(type)), ErrorCodes::LOGICAL_ERROR); } -bool Authentication::isCorrectPassword(const String & password_) const +bool Authentication::isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators & external_authenticators) const { switch (type) { @@ -71,6 +85,15 @@ bool Authentication::isCorrectPassword(const String & password_) const return encodeSHA1(first_sha1) == password_hash; } + + case LDAP_PASSWORD: + { + auto ldap_server_params = external_authenticators.getLDAPServerParams(ldap_server_name); + ldap_server_params.user = user_; + ldap_server_params.password = password_; + LDAPSimpleAuthClient ldap_client(ldap_server_params); + return ldap_client.check(); + } } throw Exception("Unknown authentication type: " + std::to_string(static_cast(type)), ErrorCodes::LOGICAL_ERROR); } diff --git a/src/Access/Authentication.h b/src/Access/Authentication.h index 3f16dc56de3..2e166a431f9 100644 --- a/src/Access/Authentication.h +++ b/src/Access/Authentication.h @@ -16,6 +16,7 @@ namespace ErrorCodes extern const int LOGICAL_ERROR; } +class ExternalAuthenticators; /// Authentication type and encrypted password for checking when an user logins. class Authentication @@ -35,6 +36,9 @@ public: /// SHA1(SHA1(password)). /// This kind of hash is used by the `mysql_native_password` authentication plugin. DOUBLE_SHA1_PASSWORD, + + /// Password is checked by a [remote] LDAP server. Connection will be made at each authentication attempt. + LDAP_PASSWORD, }; using Digest = std::vector; @@ -67,8 +71,13 @@ public: /// Allowed to use for Type::NO_PASSWORD, Type::PLAINTEXT_PASSWORD, Type::DOUBLE_SHA1_PASSWORD. Digest getPasswordDoubleSHA1() const; + /// Sets an external LDAP server name. LDAP server name is used when authentication type is LDAP_PASSWORD. + void setLDAPServerName(const String & server_name); + const String & getLDAPServerName() const; + /// Checks if the provided password is correct. Returns false if not. - bool isCorrectPassword(const String & password) const; + /// User name and external authenticators' info is used only by some specific authentication mechanisms (e.g., LDAP). + bool isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators & external_authenticators) const; friend bool operator ==(const Authentication & lhs, const Authentication & rhs) { return (lhs.type == rhs.type) && (lhs.password_hash == rhs.password_hash); } friend bool operator !=(const Authentication & lhs, const Authentication & rhs) { return !(lhs == rhs); } @@ -82,6 +91,7 @@ private: Type type = Type::NO_PASSWORD; Digest password_hash; + String ldap_server_name; }; @@ -122,6 +132,9 @@ inline void Authentication::setPassword(const String & password_) case DOUBLE_SHA1_PASSWORD: return setPasswordHashBinary(encodeDoubleSHA1(password_)); + + case LDAP_PASSWORD: + throw Exception("Cannot specify password for the 'LDAP_PASSWORD' authentication type", ErrorCodes::LOGICAL_ERROR); } throw Exception("Unknown authentication type: " + std::to_string(static_cast(type)), ErrorCodes::LOGICAL_ERROR); } @@ -145,6 +158,8 @@ inline void Authentication::setPasswordHashHex(const String & hash) inline String Authentication::getPasswordHashHex() const { + if (type == LDAP_PASSWORD) + throw Exception("Cannot get password of a user with the 'LDAP_PASSWORD' authentication type", ErrorCodes::LOGICAL_ERROR); String hex; hex.resize(password_hash.size() * 2); boost::algorithm::hex(password_hash.begin(), password_hash.end(), hex.data()); @@ -186,6 +201,9 @@ inline void Authentication::setPasswordHashBinary(const Digest & hash) password_hash = hash; return; } + + case LDAP_PASSWORD: + throw Exception("Cannot specify password for the 'LDAP_PASSWORD' authentication type", ErrorCodes::LOGICAL_ERROR); } throw Exception("Unknown authentication type: " + std::to_string(static_cast(type)), ErrorCodes::LOGICAL_ERROR); } diff --git a/src/Access/ContextAccess.cpp b/src/Access/ContextAccess.cpp index f973e93c76b..eb1fa0dd894 100644 --- a/src/Access/ContextAccess.cpp +++ b/src/Access/ContextAccess.cpp @@ -176,12 +176,12 @@ void ContextAccess::setRolesInfo(const std::shared_ptr & } -bool ContextAccess::isCorrectPassword(const String & password) const +bool ContextAccess::isCorrectPassword(const String & password, const ExternalAuthenticators & external_authenticators) const { std::lock_guard lock{mutex}; if (!user) return false; - return user->authentication.isCorrectPassword(password); + return user->authentication.isCorrectPassword(password, user_name, external_authenticators); } bool ContextAccess::isClientHostAllowed() const diff --git a/src/Access/ContextAccess.h b/src/Access/ContextAccess.h index 27bb29a878c..062ab37e414 100644 --- a/src/Access/ContextAccess.h +++ b/src/Access/ContextAccess.h @@ -26,6 +26,7 @@ struct QuotaUsage; struct Settings; class SettingsConstraints; class AccessControlManager; +class ExternalAuthenticators; class IAST; using ASTPtr = std::shared_ptr; @@ -62,7 +63,8 @@ public: UserPtr getUser() const; String getUserName() const; - bool isCorrectPassword(const String & password) const; + /// External authenticators may be used by only some of the authentication mechanisms. + bool isCorrectPassword(const String & password, const ExternalAuthenticators & external_authenticators) const; bool isClientHostAllowed() const; /// Returns information about current and enabled roles. diff --git a/src/Access/ExternalAuthenticators.cpp b/src/Access/ExternalAuthenticators.cpp new file mode 100644 index 00000000000..273048a020e --- /dev/null +++ b/src/Access/ExternalAuthenticators.cpp @@ -0,0 +1,28 @@ +#include +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int BAD_ARGUMENTS; +} + +void ExternalAuthenticators::setLDAPServerParams(const String & server, const LDAPServerParams & params) +{ + std::scoped_lock lock(mutex); + ldap_server_params.erase(server); + ldap_server_params[server] = params; +} + +LDAPServerParams ExternalAuthenticators::getLDAPServerParams(const String & server) const +{ + std::scoped_lock lock(mutex); + auto it = ldap_server_params.find(server); + if (it == ldap_server_params.end()) + throw Exception("LDAP server '" + server + "' is not configured", ErrorCodes::BAD_ARGUMENTS); + return it->second; +} + +} diff --git a/src/Access/ExternalAuthenticators.h b/src/Access/ExternalAuthenticators.h new file mode 100644 index 00000000000..f7707e0719f --- /dev/null +++ b/src/Access/ExternalAuthenticators.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include +#include + + +namespace DB +{ + +class ExternalAuthenticators +{ +public: + void setLDAPServerParams(const String & server, const LDAPServerParams & params); + LDAPServerParams getLDAPServerParams(const String & server) const; + +private: + mutable std::mutex mutex; + std::map ldap_server_params; +}; + +} diff --git a/src/Access/LDAPClient.cpp b/src/Access/LDAPClient.cpp new file mode 100644 index 00000000000..136a7af70c4 --- /dev/null +++ b/src/Access/LDAPClient.cpp @@ -0,0 +1,279 @@ +#include +#include +#include + + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int BAD_ARGUMENTS; + extern const int FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME; + extern const int LDAP_ERROR; +} + +LDAPClient::LDAPClient(const LDAPServerParams & params_) + : params(params_) +{ +} + +LDAPClient::~LDAPClient() +{ + closeConnection(); +} + +#if USE_LDAP + +namespace +{ + auto escapeForLDAP(const String & src) + { + String dest; + dest.reserve(src.size() * 2); + + for (auto ch : src) + { + switch (ch) + { + case ',': + case '\\': + case '#': + case '+': + case '<': + case '>': + case ';': + case '"': + case '=': + dest += '\\'; + break; + } + dest += ch; + } + + return dest; + } +} + +void LDAPClient::diag(const int rc) +{ + if (rc != LDAP_SUCCESS) + { + String text; + const char * raw_err_str = ldap_err2string(rc); + + if (raw_err_str) + text = raw_err_str; + + if (handle) + { + String message; + char * raw_message = nullptr; + ldap_get_option(handle, LDAP_OPT_DIAGNOSTIC_MESSAGE, &raw_message); + + if (raw_message) + { + message = raw_message; + ldap_memfree(raw_message); + raw_message = nullptr; + } + + if (!message.empty()) + { + if (!text.empty()) + text += ": "; + text += message; + } + } + + throw Exception(text, ErrorCodes::LDAP_ERROR); + } +} + +int LDAPClient::openConnection(const bool graceful_bind_failure) +{ + closeConnection(); + + { + LDAPURLDesc url; + std::memset(&url, 0, sizeof(url)); + + url.lud_scheme = const_cast(params.enable_tls == LDAPServerParams::TLSEnable::YES ? "ldaps" : "ldap"); + url.lud_host = const_cast(params.host.c_str()); + url.lud_port = params.port; + url.lud_scope = LDAP_SCOPE_DEFAULT; + + auto * uri = ldap_url_desc2str(&url); + if (!uri) + throw Exception("ldap_url_desc2str() failed", ErrorCodes::LDAP_ERROR); + + SCOPE_EXIT({ ldap_memfree(uri); }); + + diag(ldap_initialize(&handle, uri)); + if (!handle) + throw Exception("ldap_initialize() failed", ErrorCodes::LDAP_ERROR); + } + + { + int value = 0; + switch (params.protocol_version) + { + case LDAPServerParams::ProtocolVersion::V2: value = LDAP_VERSION2; break; + case LDAPServerParams::ProtocolVersion::V3: value = LDAP_VERSION3; break; + } + diag(ldap_set_option(handle, LDAP_OPT_PROTOCOL_VERSION, &value)); + } + + diag(ldap_set_option(handle, LDAP_OPT_RESTART, LDAP_OPT_ON)); + diag(ldap_set_option(handle, LDAP_OPT_KEEPCONN, LDAP_OPT_ON)); + + { + ::timeval operation_timeout; + operation_timeout.tv_sec = params.operation_timeout.count(); + operation_timeout.tv_usec = 0; + diag(ldap_set_option(handle, LDAP_OPT_TIMEOUT, &operation_timeout)); + } + + { + ::timeval network_timeout; + network_timeout.tv_sec = params.network_timeout.count(); + network_timeout.tv_usec = 0; + diag(ldap_set_option(handle, LDAP_OPT_NETWORK_TIMEOUT, &network_timeout)); + } + + { + const int search_timeout = params.search_timeout.count(); + diag(ldap_set_option(handle, LDAP_OPT_TIMELIMIT, &search_timeout)); + } + + { + const int size_limit = params.search_limit; + diag(ldap_set_option(handle, LDAP_OPT_SIZELIMIT, &size_limit)); + } + + { + int value = 0; + switch (params.tls_cert_verify) + { + case LDAPServerParams::TLSCertVerify::NEVER: value = LDAP_OPT_X_TLS_NEVER; break; + case LDAPServerParams::TLSCertVerify::ALLOW: value = LDAP_OPT_X_TLS_ALLOW; break; + case LDAPServerParams::TLSCertVerify::TRY: value = LDAP_OPT_X_TLS_TRY; break; + case LDAPServerParams::TLSCertVerify::DEMAND: value = LDAP_OPT_X_TLS_DEMAND; break; + } + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_REQUIRE_CERT, &value)); + } + + if (!params.ca_cert_dir.empty()) + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTDIR, params.ca_cert_dir.c_str())); + + if (!params.ca_cert_file.empty()) + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTFILE, params.ca_cert_file.c_str())); + + if (params.enable_tls == LDAPServerParams::TLSEnable::YES_STARTTLS) + diag(ldap_start_tls_s(handle, nullptr, nullptr)); + + int rc = LDAP_OTHER; + + switch (params.sasl_mechanism) + { + case LDAPServerParams::SASLMechanism::SIMPLE: + { + const String dn = params.auth_dn_prefix + escapeForLDAP(params.user) + params.auth_dn_suffix; + + ::berval cred; + cred.bv_val = const_cast(params.password.c_str()); + cred.bv_len = params.password.size(); + + rc = ldap_sasl_bind_s(handle, dn.c_str(), LDAP_SASL_SIMPLE, &cred, nullptr, nullptr, nullptr); + + if (!graceful_bind_failure) + diag(rc); + + break; + } + } + + return rc; +} + +void LDAPClient::openConnection() +{ + const bool graceful_bind_failure = false; + diag(openConnection(graceful_bind_failure)); +} + +void LDAPClient::closeConnection() noexcept +{ + if (!handle) + return; + + ldap_unbind_ext_s(handle, nullptr, nullptr); + handle = nullptr; +} + +bool LDAPSimpleAuthClient::check() +{ + bool result = false; + + if (params.user.empty()) + throw Exception("LDAP authentication of a user with an empty name is not allowed", ErrorCodes::BAD_ARGUMENTS); + + const bool graceful_bind_failure = true; + const auto rc = openConnection(graceful_bind_failure); + + SCOPE_EXIT({ closeConnection(); }); + + switch (rc) + { + case LDAP_SUCCESS: + { + result = true; + break; + } + + case LDAP_INVALID_CREDENTIALS: + { + result = false; + break; + } + + default: + { + result = false; + diag(rc); + break; + } + } + + return result; +} + +#else // USE_LDAP + +void LDAPClient::diag(const int) +{ + throw Exception("ClickHouse was built without LDAP support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME); +} + +int LDAPClient::openConnection(const bool) +{ + throw Exception("ClickHouse was built without LDAP support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME); +} + +void LDAPClient::openConnection() +{ + throw Exception("ClickHouse was built without LDAP support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME); +} + +void LDAPClient::closeConnection() noexcept +{ +} + +bool LDAPSimpleAuthClient::check() +{ + throw Exception("ClickHouse was built without LDAP support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME); +} + +#endif // USE_LDAP + +} diff --git a/src/Access/LDAPClient.h b/src/Access/LDAPClient.h new file mode 100644 index 00000000000..1187f2c2a21 --- /dev/null +++ b/src/Access/LDAPClient.h @@ -0,0 +1,55 @@ +#pragma once + +#if __has_include("config_core.h") +#include "config_core.h" +#endif + +#include +#include + +#if USE_LDAP +#include +#define MAYBE_NORETURN +#else +#define MAYBE_NORETURN [[noreturn]] +#endif + + +namespace DB +{ + +class LDAPClient +{ +public: + explicit LDAPClient(const LDAPServerParams & params_); + ~LDAPClient(); + + LDAPClient(const LDAPClient &) = delete; + LDAPClient(LDAPClient &&) = delete; + LDAPClient & operator= (const LDAPClient &) = delete; + LDAPClient & operator= (LDAPClient &&) = delete; + +protected: + int openConnection(const bool graceful_bind_failure = false); + MAYBE_NORETURN void openConnection(); + void closeConnection() noexcept; + MAYBE_NORETURN void diag(const int rc); + +protected: + LDAPServerParams params; +#if USE_LDAP + LDAP * handle = nullptr; +#endif +}; + +class LDAPSimpleAuthClient + : private LDAPClient +{ +public: + using LDAPClient::LDAPClient; + bool check(); +}; + +} + +#undef MAYBE_NORETURN diff --git a/src/Access/LDAPParams.h b/src/Access/LDAPParams.h new file mode 100644 index 00000000000..ed28526d29d --- /dev/null +++ b/src/Access/LDAPParams.h @@ -0,0 +1,63 @@ +#pragma once + +#include + +#include + + +namespace DB +{ + +struct LDAPServerParams +{ + enum class ProtocolVersion + { + V2, + V3 + }; + + enum class TLSEnable + { + NO, + YES_STARTTLS, + YES + }; + + enum class TLSCertVerify + { + NEVER, + ALLOW, + TRY, + DEMAND + }; + + enum class SASLMechanism + { + SIMPLE + }; + + ProtocolVersion protocol_version = ProtocolVersion::V3; + + String host; + std::uint16_t port = 636; + + TLSEnable enable_tls = TLSEnable::YES; + TLSCertVerify tls_cert_verify = TLSCertVerify::DEMAND; + String ca_cert_dir; + String ca_cert_file; + + SASLMechanism sasl_mechanism = SASLMechanism::SIMPLE; + + String auth_dn_prefix; + String auth_dn_suffix; + + String user; + String password; + + std::chrono::seconds operation_timeout{40}; + std::chrono::seconds network_timeout{30}; + std::chrono::seconds search_timeout{20}; + std::uint32_t search_limit = 100; +}; + +} diff --git a/src/Access/UsersConfigAccessStorage.cpp b/src/Access/UsersConfigAccessStorage.cpp index ce33383548f..2482bca053a 100644 --- a/src/Access/UsersConfigAccessStorage.cpp +++ b/src/Access/UsersConfigAccessStorage.cpp @@ -55,13 +55,14 @@ namespace bool has_password = config.has(user_config + ".password"); bool has_password_sha256_hex = config.has(user_config + ".password_sha256_hex"); bool has_password_double_sha1_hex = config.has(user_config + ".password_double_sha1_hex"); + bool has_ldap = config.has(user_config + ".ldap"); - if (has_password + has_password_sha256_hex + has_password_double_sha1_hex > 1) - throw Exception("More than one field of 'password', 'password_sha256_hex', 'password_double_sha1_hex' is used to specify password for user " + user_name + ". Must be only one of them.", + if (has_password + has_password_sha256_hex + has_password_double_sha1_hex + has_ldap > 1) + throw Exception("More than one field of 'password', 'password_sha256_hex', 'password_double_sha1_hex', 'ldap' is specified for user " + user_name + ". Must be only one of them.", ErrorCodes::BAD_ARGUMENTS); - if (!has_password && !has_password_sha256_hex && !has_password_double_sha1_hex) - throw Exception("Either 'password' or 'password_sha256_hex' or 'password_double_sha1_hex' must be specified for user " + user_name + ".", ErrorCodes::BAD_ARGUMENTS); + if (!has_password && !has_password_sha256_hex && !has_password_double_sha1_hex && !has_ldap) + throw Exception("Either 'password' or 'password_sha256_hex' or 'password_double_sha1_hex' or 'ldap' must be specified for user " + user_name + ".", ErrorCodes::BAD_ARGUMENTS); if (has_password) { @@ -78,6 +79,17 @@ namespace user->authentication = Authentication{Authentication::DOUBLE_SHA1_PASSWORD}; user->authentication.setPasswordHashHex(config.getString(user_config + ".password_double_sha1_hex")); } + else if (has_ldap) + { + bool has_ldap_server = config.has(user_config + ".ldap.server"); + if (!has_ldap_server) + throw Exception("Missing mandatory 'server' in 'ldap', with LDAP server name, for user " + user_name + ".", ErrorCodes::BAD_ARGUMENTS); + + const auto ldap_server_name = config.getString(user_config + ".ldap.server"); + + user->authentication = Authentication{Authentication::LDAP_PASSWORD}; + user->authentication.setLDAPServerName(ldap_server_name); + } const auto profile_name_config = user_config + ".profile"; if (config.has(profile_name_config)) diff --git a/src/Access/ya.make b/src/Access/ya.make index 970c0714a93..de56306c827 100644 --- a/src/Access/ya.make +++ b/src/Access/ya.make @@ -18,10 +18,12 @@ SRCS( EnabledRowPolicies.cpp EnabledSettings.cpp ExtendedRoleSet.cpp + ExternalAuthenticators.cpp GrantedAccess.cpp GrantedRoles.cpp IAccessEntity.cpp IAccessStorage.cpp + LDAPClient.cpp MemoryAccessStorage.cpp MultipleAccessStorage.cpp Quota.cpp diff --git a/src/Common/ErrorCodes.cpp b/src/Common/ErrorCodes.cpp index a8bd41162e3..8ab04f1b933 100644 --- a/src/Common/ErrorCodes.cpp +++ b/src/Common/ErrorCodes.cpp @@ -496,6 +496,7 @@ namespace ErrorCodes extern const int OPENCL_ERROR = 522; extern const int UNKNOWN_ROW_POLICY = 523; extern const int ALTER_OF_COLUMN_IS_FORBIDDEN = 524; + extern const int LDAP_ERROR = 525; extern const int KEEPER_EXCEPTION = 999; extern const int POCO_EXCEPTION = 1000; diff --git a/src/Core/config_core.h.in b/src/Core/config_core.h.in index 054ee9a80b7..10f6ef98c6d 100644 --- a/src/Core/config_core.h.in +++ b/src/Core/config_core.h.in @@ -8,3 +8,4 @@ #cmakedefine01 USE_EMBEDDED_COMPILER #cmakedefine01 USE_INTERNAL_LLVM_LIBRARY #cmakedefine01 USE_SSL +#cmakedefine01 USE_LDAP diff --git a/src/Interpreters/Context.cpp b/src/Interpreters/Context.cpp index dc94b32a34d..8ab5a79942f 100644 --- a/src/Interpreters/Context.cpp +++ b/src/Interpreters/Context.cpp @@ -661,7 +661,7 @@ void Context::setUser(const String & name, const String & password, const Poco:: if (new_user_id) { new_access = getAccessControlManager().getContextAccess(*new_user_id, {}, true, settings, current_database, client_info); - if (!new_access->isClientHostAllowed() || !new_access->isCorrectPassword(password)) + if (!new_access->isClientHostAllowed() || !new_access->isCorrectPassword(password, getAccessControlManager().getExternalAuthenticators())) { new_user_id = {}; new_access = nullptr; diff --git a/src/Parsers/ASTCreateUserQuery.cpp b/src/Parsers/ASTCreateUserQuery.cpp index c8e2a76dfa2..fdf2dfdf81f 100644 --- a/src/Parsers/ASTCreateUserQuery.cpp +++ b/src/Parsers/ASTCreateUserQuery.cpp @@ -35,6 +35,10 @@ namespace settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << "double_sha1_hash BY " << (settings.hilite ? IAST::hilite_none : "") << quoteString(authentication.getPasswordHashHex()); break; + case Authentication::Type::LDAP_PASSWORD: + settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << "ldap BY " << (settings.hilite ? IAST::hilite_none : "") + << quoteString(authentication.getLDAPServerName()); + break; } } diff --git a/src/Parsers/ASTCreateUserQuery.h b/src/Parsers/ASTCreateUserQuery.h index 54dc51d783b..e954adc7b53 100644 --- a/src/Parsers/ASTCreateUserQuery.h +++ b/src/Parsers/ASTCreateUserQuery.h @@ -12,14 +12,14 @@ class ASTExtendedRoleSet; class ASTSettingsProfileElements; /** CREATE USER [IF NOT EXISTS | OR REPLACE] name - * [IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH}] BY {'password'|'hash'}] + * [IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH|LDAP}] BY {'password'|'hash'|'server_name'}] * [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [DEFAULT ROLE role [,...]] * [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] * * ALTER USER [IF EXISTS] name * [RENAME TO new_name] - * [IDENTIFIED [WITH {PLAINTEXT_PASSWORD|SHA256_PASSWORD|DOUBLE_SHA1_PASSWORD}] BY {'password'|'hash'}] + * [IDENTIFIED [WITH {PLAINTEXT_PASSWORD|SHA256_PASSWORD|DOUBLE_SHA1_PASSWORD|LDAP}] BY {'password'|'hash'|'server_name'}] * [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ] * [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] diff --git a/src/Parsers/ParserCreateUserQuery.cpp b/src/Parsers/ParserCreateUserQuery.cpp index 76a06a0282f..e07d76e6f32 100644 --- a/src/Parsers/ParserCreateUserQuery.cpp +++ b/src/Parsers/ParserCreateUserQuery.cpp @@ -125,6 +125,17 @@ namespace return true; } + if (ParserKeyword{"LDAP"}.ignore(pos, expected)) + { + String server_name; + if (!parseByPassword(pos, expected, server_name)) + return false; + + authentication = Authentication{Authentication::LDAP_PASSWORD}; + authentication->setLDAPServerName(server_name); + return true; + } + if (!ParserKeyword{"NO_PASSWORD"}.ignore(pos, expected)) return false; diff --git a/src/Parsers/ParserCreateUserQuery.h b/src/Parsers/ParserCreateUserQuery.h index d609894a7ec..e7235279584 100644 --- a/src/Parsers/ParserCreateUserQuery.h +++ b/src/Parsers/ParserCreateUserQuery.h @@ -7,13 +7,13 @@ namespace DB { /** Parses queries like * CREATE USER [IF NOT EXISTS | OR REPLACE] name - * [IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH}] BY {'password'|'hash'}] + * [IDENTIFIED [WITH {NO_PASSWORD|PLAINTEXT_PASSWORD|SHA256_PASSWORD|SHA256_HASH|DOUBLE_SHA1_PASSWORD|DOUBLE_SHA1_HASH|LDAP}] BY {'password'|'hash'|'server_name'}] * [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] * * ALTER USER [IF EXISTS] name * [RENAME TO new_name] - * [IDENTIFIED [WITH {PLAINTEXT_PASSWORD|SHA256_PASSWORD|DOUBLE_SHA1_PASSWORD}] BY {'password'|'hash'}] + * [IDENTIFIED [WITH {PLAINTEXT_PASSWORD|SHA256_PASSWORD|DOUBLE_SHA1_PASSWORD|LDAP}] BY {'password'|'hash'|'server_name'}] * [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] */ From 856245d76676b2f25f7959e1be9f5b2d5fe2cf8a Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Thu, 28 May 2020 01:40:56 +0400 Subject: [PATCH 002/143] Revert merge artefacts --- contrib/cppkafka | 2 +- contrib/grpc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/cppkafka b/contrib/cppkafka index 9b184d881c1..f555ee36aaa 160000 --- a/contrib/cppkafka +++ b/contrib/cppkafka @@ -1 +1 @@ -Subproject commit 9b184d881c15cc50784b28688c7c99d3d764db24 +Subproject commit f555ee36aaa74d17ca0dab3ce472070a610b2966 diff --git a/contrib/grpc b/contrib/grpc index c1d176528fd..8aea4e168e7 160000 --- a/contrib/grpc +++ b/contrib/grpc @@ -1 +1 @@ -Subproject commit c1d176528fd8da9dd4066d16554bcd216d29033f +Subproject commit 8aea4e168e78f3eb9828080740fc8cb73d53bf79 From d4fd018715297bc97d714a0d22a6416d6a5e6081 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Thu, 28 May 2020 02:54:14 +0400 Subject: [PATCH 003/143] Fix linking errors in parser-related test executables --- src/Access/Authentication.cpp | 10 ---------- src/Access/Authentication.h | 10 ++++++++++ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Access/Authentication.cpp b/src/Access/Authentication.cpp index e7e8b10aabc..9c8956e9253 100644 --- a/src/Access/Authentication.cpp +++ b/src/Access/Authentication.cpp @@ -13,16 +13,6 @@ namespace ErrorCodes extern const int BAD_ARGUMENTS; } -const String & Authentication::getLDAPServerName() const -{ - return ldap_server_name; -} - -void Authentication::setLDAPServerName(const String & server_name) -{ - ldap_server_name = server_name; -} - Authentication::Digest Authentication::getPasswordDoubleSHA1() const { switch (type) diff --git a/src/Access/Authentication.h b/src/Access/Authentication.h index 2e166a431f9..903b8046a5d 100644 --- a/src/Access/Authentication.h +++ b/src/Access/Authentication.h @@ -208,4 +208,14 @@ inline void Authentication::setPasswordHashBinary(const Digest & hash) throw Exception("Unknown authentication type: " + std::to_string(static_cast(type)), ErrorCodes::LOGICAL_ERROR); } +inline const String & Authentication::getLDAPServerName() const +{ + return ldap_server_name; +} + +inline void Authentication::setLDAPServerName(const String & server_name) +{ + ldap_server_name = server_name; +} + } From f1cfc7b472204696f0aaae391e915d62888ccdd2 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 29 May 2020 11:47:01 +0400 Subject: [PATCH 004/143] Rename LDAP_PASSWORD to LDAP_SERVER and use "ldap_server" as a string key Some refactoring --- src/Access/AccessControlManager.cpp | 112 ----------------------- src/Access/Authentication.cpp | 9 +- src/Access/Authentication.h | 37 ++++---- src/Access/ExternalAuthenticators.cpp | 113 ++++++++++++++++++++++++ src/Access/ExternalAuthenticators.h | 12 +++ src/Access/LDAPClient.cpp | 17 ++-- src/Access/LDAPClient.h | 8 +- src/Access/UsersConfigAccessStorage.cpp | 4 +- src/Parsers/ASTCreateUserQuery.cpp | 7 +- src/Parsers/ASTCreateUserQuery.h | 4 +- src/Parsers/ParserCreateUserQuery.cpp | 6 +- src/Parsers/ParserCreateUserQuery.h | 4 +- src/Server/MySQLHandler.cpp | 2 +- 13 files changed, 172 insertions(+), 163 deletions(-) diff --git a/src/Access/AccessControlManager.cpp b/src/Access/AccessControlManager.cpp index fc659d8bacb..07002971734 100644 --- a/src/Access/AccessControlManager.cpp +++ b/src/Access/AccessControlManager.cpp @@ -12,19 +12,11 @@ #include #include #include -#include -#include #include namespace DB { - -namespace ErrorCodes -{ - extern const int BAD_ARGUMENTS; -} - namespace { std::vector> createStorages() @@ -41,110 +33,6 @@ namespace constexpr size_t DISK_ACCESS_STORAGE_INDEX = 0; constexpr size_t USERS_CONFIG_ACCESS_STORAGE_INDEX = 1; - - auto parseLDAPServer(const Poco::Util::AbstractConfiguration & config, const String & ldap_server_name) - { - LDAPServerParams params; - - const String ldap_server_config = "ldap_servers." + ldap_server_name; - - const bool has_host = config.has(ldap_server_config + ".host"); - const bool has_port = config.has(ldap_server_config + ".port"); - const bool has_auth_dn_prefix = config.has(ldap_server_config + ".auth_dn_prefix"); - const bool has_auth_dn_suffix = config.has(ldap_server_config + ".auth_dn_suffix"); - const bool has_enable_tls = config.has(ldap_server_config + ".enable_tls"); - const bool has_tls_cert_verify = config.has(ldap_server_config + ".tls_cert_verify"); - const bool has_ca_cert_dir = config.has(ldap_server_config + ".ca_cert_dir"); - const bool has_ca_cert_file = config.has(ldap_server_config + ".ca_cert_file"); - - if (!has_host) - throw Exception("Missing 'host' entry", ErrorCodes::BAD_ARGUMENTS); - - params.host = config.getString(ldap_server_config + ".host"); - - if (params.host.empty()) - throw Exception("Empty 'host' entry", ErrorCodes::BAD_ARGUMENTS); - - if (has_auth_dn_prefix) - params.auth_dn_prefix = config.getString(ldap_server_config + ".auth_dn_prefix"); - - if (has_auth_dn_suffix) - params.auth_dn_suffix = config.getString(ldap_server_config + ".auth_dn_suffix"); - - if (has_enable_tls) - { - String enable_tls_lc_str = config.getString(ldap_server_config + ".enable_tls"); - boost::to_lower(enable_tls_lc_str); - - if (enable_tls_lc_str == "starttls") - params.enable_tls = LDAPServerParams::TLSEnable::YES_STARTTLS; - else if (config.getBool(ldap_server_config + ".enable_tls")) - params.enable_tls = LDAPServerParams::TLSEnable::YES; - else - params.enable_tls = LDAPServerParams::TLSEnable::NO; - } - - if (has_tls_cert_verify) - { - String tls_cert_verify_lc_str = config.getString(ldap_server_config + ".tls_cert_verify"); - boost::to_lower(tls_cert_verify_lc_str); - - if (tls_cert_verify_lc_str == "never") - params.tls_cert_verify = LDAPServerParams::TLSCertVerify::NEVER; - else if (tls_cert_verify_lc_str == "allow") - params.tls_cert_verify = LDAPServerParams::TLSCertVerify::ALLOW; - else if (tls_cert_verify_lc_str == "try") - params.tls_cert_verify = LDAPServerParams::TLSCertVerify::TRY; - else if (tls_cert_verify_lc_str == "demand") - params.tls_cert_verify = LDAPServerParams::TLSCertVerify::DEMAND; - else - throw Exception("Bad value for 'tls_cert_verify' entry, allowed values are: 'never', 'allow', 'try', 'demand'", ErrorCodes::BAD_ARGUMENTS); - } - - if (has_ca_cert_dir) - params.ca_cert_dir = config.getString(ldap_server_config + ".ca_cert_dir"); - - if (has_ca_cert_file) - params.ca_cert_file = config.getString(ldap_server_config + ".ca_cert_file"); - - if (has_port) - { - const auto port = config.getInt64(ldap_server_config + ".port"); - if (port < 0 || port > 65535) - throw Exception("Bad value for 'port' entry", ErrorCodes::BAD_ARGUMENTS); - - params.port = port; - } - else - params.port = (params.enable_tls == LDAPServerParams::TLSEnable::YES ? 636 : 389); - - return params; - } - - void parseAndAddLDAPServers(ExternalAuthenticators & external_authenticators, const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) - { - Poco::Util::AbstractConfiguration::Keys ldap_server_names; - config.keys("ldap_servers", ldap_server_names); - - for (const auto & ldap_server_name : ldap_server_names) - { - try - { - external_authenticators.setLDAPServerParams(ldap_server_name, parseLDAPServer(config, ldap_server_name)); - } - catch (...) - { - tryLogCurrentException(log, "Could not parse LDAP server " + backQuote(ldap_server_name)); - } - } - } - - auto parseExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) - { - auto external_authenticators = std::make_unique(); - parseAndAddLDAPServers(*external_authenticators, config, log); - return external_authenticators; - } } diff --git a/src/Access/Authentication.cpp b/src/Access/Authentication.cpp index 4d49d205040..970cb89ac10 100644 --- a/src/Access/Authentication.cpp +++ b/src/Access/Authentication.cpp @@ -13,6 +13,7 @@ namespace ErrorCodes extern const int NOT_IMPLEMENTED; } + Authentication::Digest Authentication::getPasswordDoubleSHA1() const { switch (type) @@ -38,8 +39,8 @@ Authentication::Digest Authentication::getPasswordDoubleSHA1() const case DOUBLE_SHA1_PASSWORD: return password_hash; - case LDAP_PASSWORD: - throw Exception("Cannot get password double SHA1 for user with 'LDAP_PASSWORD' authentication.", ErrorCodes::BAD_ARGUMENTS); + case LDAP_SERVER: + throw Exception("Cannot get password double SHA1 for user with 'LDAP_SERVER' authentication.", ErrorCodes::BAD_ARGUMENTS); case MAX_TYPE: break; @@ -79,9 +80,9 @@ bool Authentication::isCorrectPassword(const String & password_, const String & return encodeSHA1(first_sha1) == password_hash; } - case LDAP_PASSWORD: + case LDAP_SERVER: { - auto ldap_server_params = external_authenticators.getLDAPServerParams(ldap_server_name); + auto ldap_server_params = external_authenticators.getLDAPServerParams(server_name); ldap_server_params.user = user_; ldap_server_params.password = password_; LDAPSimpleAuthClient ldap_client(ldap_server_params); diff --git a/src/Access/Authentication.h b/src/Access/Authentication.h index 65f45db499b..35ff0fa1d32 100644 --- a/src/Access/Authentication.h +++ b/src/Access/Authentication.h @@ -40,7 +40,7 @@ public: DOUBLE_SHA1_PASSWORD, /// Password is checked by a [remote] LDAP server. Connection will be made at each authentication attempt. - LDAP_PASSWORD, + LDAP_SERVER, MAX_TYPE, }; @@ -82,12 +82,13 @@ public: /// Allowed to use for Type::NO_PASSWORD, Type::PLAINTEXT_PASSWORD, Type::DOUBLE_SHA1_PASSWORD. Digest getPasswordDoubleSHA1() const; - /// Sets an external LDAP server name. LDAP server name is used when authentication type is LDAP_PASSWORD. - void setLDAPServerName(const String & server_name); - const String & getLDAPServerName() const; + /// Sets an external authentication server name. + /// When authentication type is LDAP_SERVER, server name is expected to be the name of a preconfigured LDAP server. + const String & getServerName() const; + void setServerName(const String & server_name_); /// Checks if the provided password is correct. Returns false if not. - /// User name and external authenticators' info is used only by some specific authentication mechanisms (e.g., LDAP). + /// User name and external authenticators' info are used only by some specific authentication type (e.g., LDAP_SERVER). bool isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators & external_authenticators) const; friend bool operator ==(const Authentication & lhs, const Authentication & rhs) { return (lhs.type == rhs.type) && (lhs.password_hash == rhs.password_hash); } @@ -102,7 +103,7 @@ private: Type type = Type::NO_PASSWORD; Digest password_hash; - String ldap_server_name; + String server_name; }; @@ -137,9 +138,9 @@ inline const Authentication::TypeInfo & Authentication::TypeInfo::get(Type type_ static const auto info = make_info("DOUBLE_SHA1_PASSWORD"); return info; } - case LDAP_PASSWORD: + case LDAP_SERVER: { - static const auto info = make_info("LDAP"); + static const auto info = make_info("LDAP_SERVER"); return info; } case MAX_TYPE: break; @@ -191,8 +192,8 @@ inline void Authentication::setPassword(const String & password_) case DOUBLE_SHA1_PASSWORD: return setPasswordHashBinary(encodeDoubleSHA1(password_)); - case LDAP_PASSWORD: - throw Exception("Cannot specify password for the 'LDAP_PASSWORD' authentication type", ErrorCodes::LOGICAL_ERROR); + case LDAP_SERVER: + throw Exception("Cannot specify password for the 'LDAP_SERVER' authentication type", ErrorCodes::LOGICAL_ERROR); case MAX_TYPE: break; } @@ -218,8 +219,8 @@ inline void Authentication::setPasswordHashHex(const String & hash) inline String Authentication::getPasswordHashHex() const { - if (type == LDAP_PASSWORD) - throw Exception("Cannot get password of a user with the 'LDAP_PASSWORD' authentication type", ErrorCodes::LOGICAL_ERROR); + if (type == LDAP_SERVER) + throw Exception("Cannot get password of a user with the 'LDAP_SERVER' authentication type", ErrorCodes::LOGICAL_ERROR); String hex; hex.resize(password_hash.size() * 2); boost::algorithm::hex(password_hash.begin(), password_hash.end(), hex.data()); @@ -262,22 +263,22 @@ inline void Authentication::setPasswordHashBinary(const Digest & hash) return; } - case LDAP_PASSWORD: - throw Exception("Cannot specify password for the 'LDAP_PASSWORD' authentication type", ErrorCodes::LOGICAL_ERROR); + case LDAP_SERVER: + throw Exception("Cannot specify password for the 'LDAP_SERVER' authentication type", ErrorCodes::LOGICAL_ERROR); case MAX_TYPE: break; } throw Exception("setPasswordHashBinary(): authentication type " + toString(type) + " not supported", ErrorCodes::NOT_IMPLEMENTED); } -inline const String & Authentication::getLDAPServerName() const +inline const String & Authentication::getServerName() const { - return ldap_server_name; + return server_name; } -inline void Authentication::setLDAPServerName(const String & server_name) +inline void Authentication::setServerName(const String & server_name_) { - ldap_server_name = server_name; + server_name = server_name_; } } diff --git a/src/Access/ExternalAuthenticators.cpp b/src/Access/ExternalAuthenticators.cpp index 273048a020e..97f2f24a72e 100644 --- a/src/Access/ExternalAuthenticators.cpp +++ b/src/Access/ExternalAuthenticators.cpp @@ -1,5 +1,9 @@ #include #include +#include +#include +#include + namespace DB { @@ -9,6 +13,108 @@ namespace ErrorCodes extern const int BAD_ARGUMENTS; } +namespace +{ + +auto parseLDAPServer(const Poco::Util::AbstractConfiguration & config, const String & ldap_server_name) +{ + LDAPServerParams params; + + const String ldap_server_config = "ldap_servers." + ldap_server_name; + + const bool has_host = config.has(ldap_server_config + ".host"); + const bool has_port = config.has(ldap_server_config + ".port"); + const bool has_auth_dn_prefix = config.has(ldap_server_config + ".auth_dn_prefix"); + const bool has_auth_dn_suffix = config.has(ldap_server_config + ".auth_dn_suffix"); + const bool has_enable_tls = config.has(ldap_server_config + ".enable_tls"); + const bool has_tls_cert_verify = config.has(ldap_server_config + ".tls_cert_verify"); + const bool has_ca_cert_dir = config.has(ldap_server_config + ".ca_cert_dir"); + const bool has_ca_cert_file = config.has(ldap_server_config + ".ca_cert_file"); + + if (!has_host) + throw Exception("Missing 'host' entry", ErrorCodes::BAD_ARGUMENTS); + + params.host = config.getString(ldap_server_config + ".host"); + + if (params.host.empty()) + throw Exception("Empty 'host' entry", ErrorCodes::BAD_ARGUMENTS); + + if (has_auth_dn_prefix) + params.auth_dn_prefix = config.getString(ldap_server_config + ".auth_dn_prefix"); + + if (has_auth_dn_suffix) + params.auth_dn_suffix = config.getString(ldap_server_config + ".auth_dn_suffix"); + + if (has_enable_tls) + { + String enable_tls_lc_str = config.getString(ldap_server_config + ".enable_tls"); + boost::to_lower(enable_tls_lc_str); + + if (enable_tls_lc_str == "starttls") + params.enable_tls = LDAPServerParams::TLSEnable::YES_STARTTLS; + else if (config.getBool(ldap_server_config + ".enable_tls")) + params.enable_tls = LDAPServerParams::TLSEnable::YES; + else + params.enable_tls = LDAPServerParams::TLSEnable::NO; + } + + if (has_tls_cert_verify) + { + String tls_cert_verify_lc_str = config.getString(ldap_server_config + ".tls_cert_verify"); + boost::to_lower(tls_cert_verify_lc_str); + + if (tls_cert_verify_lc_str == "never") + params.tls_cert_verify = LDAPServerParams::TLSCertVerify::NEVER; + else if (tls_cert_verify_lc_str == "allow") + params.tls_cert_verify = LDAPServerParams::TLSCertVerify::ALLOW; + else if (tls_cert_verify_lc_str == "try") + params.tls_cert_verify = LDAPServerParams::TLSCertVerify::TRY; + else if (tls_cert_verify_lc_str == "demand") + params.tls_cert_verify = LDAPServerParams::TLSCertVerify::DEMAND; + else + throw Exception("Bad value for 'tls_cert_verify' entry, allowed values are: 'never', 'allow', 'try', 'demand'", ErrorCodes::BAD_ARGUMENTS); + } + + if (has_ca_cert_dir) + params.ca_cert_dir = config.getString(ldap_server_config + ".ca_cert_dir"); + + if (has_ca_cert_file) + params.ca_cert_file = config.getString(ldap_server_config + ".ca_cert_file"); + + if (has_port) + { + const auto port = config.getInt64(ldap_server_config + ".port"); + if (port < 0 || port > 65535) + throw Exception("Bad value for 'port' entry", ErrorCodes::BAD_ARGUMENTS); + + params.port = port; + } + else + params.port = (params.enable_tls == LDAPServerParams::TLSEnable::YES ? 636 : 389); + + return params; +} + +void parseAndAddLDAPServers(ExternalAuthenticators & external_authenticators, const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) +{ + Poco::Util::AbstractConfiguration::Keys ldap_server_names; + config.keys("ldap_servers", ldap_server_names); + + for (const auto & ldap_server_name : ldap_server_names) + { + try + { + external_authenticators.setLDAPServerParams(ldap_server_name, parseLDAPServer(config, ldap_server_name)); + } + catch (...) + { + tryLogCurrentException(log, "Could not parse LDAP server " + backQuote(ldap_server_name)); + } + } +} + +} + void ExternalAuthenticators::setLDAPServerParams(const String & server, const LDAPServerParams & params) { std::scoped_lock lock(mutex); @@ -25,4 +131,11 @@ LDAPServerParams ExternalAuthenticators::getLDAPServerParams(const String & serv return it->second; } +std::unique_ptr parseExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) +{ + auto external_authenticators = std::make_unique(); + parseAndAddLDAPServers(*external_authenticators, config, log); + return external_authenticators; +} + } diff --git a/src/Access/ExternalAuthenticators.h b/src/Access/ExternalAuthenticators.h index f7707e0719f..1910243781f 100644 --- a/src/Access/ExternalAuthenticators.h +++ b/src/Access/ExternalAuthenticators.h @@ -4,9 +4,19 @@ #include #include +#include #include +namespace Poco { + class Logger; + namespace Util + { + class AbstractConfiguration; + } +} + + namespace DB { @@ -21,4 +31,6 @@ private: std::map ldap_server_params; }; +std::unique_ptr parseExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log); + } diff --git a/src/Access/LDAPClient.cpp b/src/Access/LDAPClient.cpp index 136a7af70c4..d7f58b0ec50 100644 --- a/src/Access/LDAPClient.cpp +++ b/src/Access/LDAPClient.cpp @@ -23,6 +23,12 @@ LDAPClient::~LDAPClient() closeConnection(); } +void LDAPClient::openConnection() +{ + const bool graceful_bind_failure = false; + diag(openConnection(graceful_bind_failure)); +} + #if USE_LDAP namespace @@ -196,12 +202,6 @@ int LDAPClient::openConnection(const bool graceful_bind_failure) return rc; } -void LDAPClient::openConnection() -{ - const bool graceful_bind_failure = false; - diag(openConnection(graceful_bind_failure)); -} - void LDAPClient::closeConnection() noexcept { if (!handle) @@ -260,11 +260,6 @@ int LDAPClient::openConnection(const bool) throw Exception("ClickHouse was built without LDAP support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME); } -void LDAPClient::openConnection() -{ - throw Exception("ClickHouse was built without LDAP support", ErrorCodes::FEATURE_IS_NOT_ENABLED_AT_BUILD_TIME); -} - void LDAPClient::closeConnection() noexcept { } diff --git a/src/Access/LDAPClient.h b/src/Access/LDAPClient.h index 1187f2c2a21..a07dc93f4b1 100644 --- a/src/Access/LDAPClient.h +++ b/src/Access/LDAPClient.h @@ -30,13 +30,13 @@ public: LDAPClient & operator= (LDAPClient &&) = delete; protected: - int openConnection(const bool graceful_bind_failure = false); - MAYBE_NORETURN void openConnection(); - void closeConnection() noexcept; MAYBE_NORETURN void diag(const int rc); + MAYBE_NORETURN void openConnection(); + int openConnection(const bool graceful_bind_failure = false); + void closeConnection() noexcept; protected: - LDAPServerParams params; + const LDAPServerParams params; #if USE_LDAP LDAP * handle = nullptr; #endif diff --git a/src/Access/UsersConfigAccessStorage.cpp b/src/Access/UsersConfigAccessStorage.cpp index 883468f4963..38925142460 100644 --- a/src/Access/UsersConfigAccessStorage.cpp +++ b/src/Access/UsersConfigAccessStorage.cpp @@ -89,8 +89,8 @@ namespace const auto ldap_server_name = config.getString(user_config + ".ldap.server"); - user->authentication = Authentication{Authentication::LDAP_PASSWORD}; - user->authentication.setLDAPServerName(ldap_server_name); + user->authentication = Authentication{Authentication::LDAP_SERVER}; + user->authentication.setServerName(ldap_server_name); } const auto profile_name_config = user_config + ".profile"; diff --git a/src/Parsers/ASTCreateUserQuery.cpp b/src/Parsers/ASTCreateUserQuery.cpp index 9ad89fc02bd..087c8160bad 100644 --- a/src/Parsers/ASTCreateUserQuery.cpp +++ b/src/Parsers/ASTCreateUserQuery.cpp @@ -34,7 +34,7 @@ namespace String authentication_type_name = Authentication::TypeInfo::get(authentication_type).name; std::optional password; - if (show_password || authentication_type == Authentication::LDAP_PASSWORD) + if (show_password || authentication_type == Authentication::LDAP_SERVER) { switch (authentication_type) { @@ -55,10 +55,9 @@ namespace password = authentication.getPasswordHashHex(); break; } - case Authentication::LDAP_PASSWORD: + case Authentication::LDAP_SERVER: { - authentication_type_name = "ldap"; - password = authentication.getLDAPServerName(); + password = authentication.getServerName(); break; } diff --git a/src/Parsers/ASTCreateUserQuery.h b/src/Parsers/ASTCreateUserQuery.h index 42ec3fb877b..c9657b9abdf 100644 --- a/src/Parsers/ASTCreateUserQuery.h +++ b/src/Parsers/ASTCreateUserQuery.h @@ -12,14 +12,14 @@ class ASTExtendedRoleSet; class ASTSettingsProfileElements; /** CREATE USER [IF NOT EXISTS | OR REPLACE] name - * [NOT IDENTIFIED | IDENTIFIED [WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|ldap}] BY {'password'|'hash'|'server_name'}] + * [NOT IDENTIFIED | IDENTIFIED [WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|ldap_server}] BY {'password'|'hash'|'server_name'}] * [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [DEFAULT ROLE role [,...]] * [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] * * ALTER USER [IF EXISTS] name * [RENAME TO new_name] - * [NOT IDENTIFIED | IDENTIFIED [WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|ldap}] BY {'password'|'hash'|'server_name'}] + * [NOT IDENTIFIED | IDENTIFIED [WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|ldap_server}] BY {'password'|'hash'|'server_name'}] * [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [DEFAULT ROLE role [,...] | ALL | ALL EXCEPT role [,...] ] * [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] diff --git a/src/Parsers/ParserCreateUserQuery.cpp b/src/Parsers/ParserCreateUserQuery.cpp index f1b741a1056..9a8acd61b3a 100644 --- a/src/Parsers/ParserCreateUserQuery.cpp +++ b/src/Parsers/ParserCreateUserQuery.cpp @@ -60,8 +60,8 @@ namespace if (ParserKeyword{Authentication::TypeInfo::get(check_type).raw_name}.ignore(pos, expected)) { type = check_type; - expect_password = (check_type != Authentication::NO_PASSWORD && check_type != Authentication::LDAP_PASSWORD); - expect_server = (check_type == Authentication::LDAP_PASSWORD); + expect_password = (check_type != Authentication::NO_PASSWORD && check_type != Authentication::LDAP_SERVER); + expect_server = (check_type == Authentication::LDAP_SERVER); break; } } @@ -105,7 +105,7 @@ namespace else if (expect_hash) authentication->setPasswordHashHex(value); else if (expect_server) - authentication->setLDAPServerName(value); + authentication->setServerName(value); return true; }); diff --git a/src/Parsers/ParserCreateUserQuery.h b/src/Parsers/ParserCreateUserQuery.h index b4e1918aaed..2df8ee5bcff 100644 --- a/src/Parsers/ParserCreateUserQuery.h +++ b/src/Parsers/ParserCreateUserQuery.h @@ -7,13 +7,13 @@ namespace DB { /** Parses queries like * CREATE USER [IF NOT EXISTS | OR REPLACE] name - * [NOT IDENTIFIED | IDENTIFIED [WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|ldap}] BY {'password'|'hash'|'server_name'}] + * [NOT IDENTIFIED | IDENTIFIED [WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|ldap_server}] BY {'password'|'hash'|'server_name'}] * [HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] * * ALTER USER [IF EXISTS] name * [RENAME TO new_name] - * [NOT IDENTIFIED | IDENTIFIED [WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|ldap}] BY {'password'|'hash'|'server_name'}] + * [NOT IDENTIFIED | IDENTIFIED [WITH {no_password|plaintext_password|sha256_password|sha256_hash|double_sha1_password|double_sha1_hash|ldap_server}] BY {'password'|'hash'|'server_name'}] * [[ADD|DROP] HOST {LOCAL | NAME 'name' | REGEXP 'name_regexp' | IP 'address' | LIKE 'pattern'} [,...] | ANY | NONE] * [SETTINGS variable [= value] [MIN [=] min_value] [MAX [=] max_value] [READONLY|WRITABLE] | PROFILE 'profile_name'] [,...] */ diff --git a/src/Server/MySQLHandler.cpp b/src/Server/MySQLHandler.cpp index a053ec77967..2e88d17ee46 100644 --- a/src/Server/MySQLHandler.cpp +++ b/src/Server/MySQLHandler.cpp @@ -222,7 +222,7 @@ void MySQLHandler::authenticate(const String & user_name, const String & auth_pl // For compatibility with JavaScript MySQL client, Native41 authentication plugin is used when possible (if password is specified using double SHA1). Otherwise SHA256 plugin is used. auto user = connection_context.getAccessControlManager().read(user_name); const DB::Authentication::Type user_auth_type = user->authentication.getType(); - if (user_auth_type != DB::Authentication::LDAP_PASSWORD && user_auth_type != DB::Authentication::DOUBLE_SHA1_PASSWORD && user_auth_type != DB::Authentication::PLAINTEXT_PASSWORD && user_auth_type != DB::Authentication::NO_PASSWORD) + if (user_auth_type != DB::Authentication::LDAP_SERVER && user_auth_type != DB::Authentication::DOUBLE_SHA1_PASSWORD && user_auth_type != DB::Authentication::PLAINTEXT_PASSWORD && user_auth_type != DB::Authentication::NO_PASSWORD) { authPluginSSL(); } From bb68768ce1f95d9eb38b96a75ecee6d7819d01ab Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 29 May 2020 13:30:07 +0400 Subject: [PATCH 005/143] Change auth_params type to string Write LDAP_SERVER params (server name) to auth_params in JSON --- src/Storages/System/StorageSystemUsers.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Storages/System/StorageSystemUsers.cpp b/src/Storages/System/StorageSystemUsers.cpp index e0755fe59ab..a1e7eba7232 100644 --- a/src/Storages/System/StorageSystemUsers.cpp +++ b/src/Storages/System/StorageSystemUsers.cpp @@ -12,6 +12,10 @@ #include #include #include +#include +#include +#include +#include namespace DB @@ -35,7 +39,7 @@ NamesAndTypesList StorageSystemUsers::getNamesAndTypes() {"id", std::make_shared()}, {"storage", std::make_shared()}, {"auth_type", std::make_shared(getAuthenticationTypeEnumValues())}, - {"auth_params", std::make_shared(std::make_shared())}, + {"auth_params", std::make_shared()}, {"host_ip", std::make_shared(std::make_shared())}, {"host_names", std::make_shared(std::make_shared())}, {"host_names_regexp", std::make_shared(std::make_shared())}, @@ -59,8 +63,7 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, const Context & auto & column_id = assert_cast(*res_columns[column_index++]).getData(); auto & column_storage = assert_cast(*res_columns[column_index++]); auto & column_auth_type = assert_cast(*res_columns[column_index++]).getData(); - auto & column_auth_params = assert_cast(assert_cast(*res_columns[column_index]).getData()); - auto & column_auth_params_offsets = assert_cast(*res_columns[column_index++]).getOffsets(); + auto & column_auth_params = assert_cast(*res_columns[column_index++]); auto & column_host_ip = assert_cast(assert_cast(*res_columns[column_index]).getData()); auto & column_host_ip_offsets = assert_cast(*res_columns[column_index++]).getOffsets(); auto & column_host_names = assert_cast(assert_cast(*res_columns[column_index]).getData()); @@ -86,7 +89,18 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, const Context & column_id.push_back(id); column_storage.insertData(storage_name.data(), storage_name.length()); column_auth_type.push_back(static_cast(authentication.getType())); - column_auth_params_offsets.push_back(column_auth_params.size()); + + if (authentication.getType() == Authentication::Type::LDAP_SERVER) + { + Poco::JSON::Object auth_params_json; + auth_params_json.set("server", authentication.getServerName()); + + std::ostringstream oss; + Poco::JSON::Stringifier::stringify(auth_params_json, oss); + const auto str = oss.str(); + + column_auth_params.insertData(str.data(), str.size()); + } if (allowed_hosts.containsAnyHost()) { From d9ca9cd9b2e6d44d4ec8160020b98d8f2340ba90 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 29 May 2020 14:00:12 +0400 Subject: [PATCH 006/143] Compilation fix Typo fix --- cmake/Modules/FindOpenLDAP.cmake | 10 +++++----- cmake/find/ldap.cmake | 7 +++++-- cmake/tools.cmake | 2 +- contrib/CMakeLists.txt | 2 +- src/Access/LDAPClient.cpp | 2 ++ src/CMakeLists.txt | 2 +- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/cmake/Modules/FindOpenLDAP.cmake b/cmake/Modules/FindOpenLDAP.cmake index c33eafdcb2e..ec559e9a7b5 100644 --- a/cmake/Modules/FindOpenLDAP.cmake +++ b/cmake/Modules/FindOpenLDAP.cmake @@ -7,7 +7,7 @@ # # Sets values of: # OPENLDAP_FOUND - TRUE if found -# OPENLDAP_INCLUDE_DIR - path to the include directory +# OPENLDAP_INCLUDE_DIRS - list of paths to the include directories # OPENLDAP_LIBRARIES - paths to the libldap and liblber libraries # OPENLDAP_LDAP_LIBRARY - paths to the libldap library # OPENLDAP_LBER_LIBRARY - paths to the liblber library @@ -28,11 +28,11 @@ if(OPENLDAP_USE_REENTRANT_LIBS) endif() if(OPENLDAP_ROOT_DIR) - find_path(OPENLDAP_INCLUDE_DIR NAMES "ldap.h" "lber.h" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "include" NO_DEFAULT_PATH) + find_path(OPENLDAP_INCLUDE_DIRS NAMES "ldap.h" "lber.h" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "include" NO_DEFAULT_PATH) find_library(OPENLDAP_LDAP_LIBRARY NAMES "ldap${_r_suffix}" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) find_library(OPENLDAP_LBER_LIBRARY NAMES "lber" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) else() - find_path(OPENLDAP_INCLUDE_DIR NAMES "ldap.h" "lber.h") + find_path(OPENLDAP_INCLUDE_DIRS NAMES "ldap.h" "lber.h") find_library(OPENLDAP_LDAP_LIBRARY NAMES "ldap${_r_suffix}") find_library(OPENLDAP_LBER_LIBRARY NAMES "lber") endif() @@ -44,10 +44,10 @@ set(OPENLDAP_LIBRARIES ${OPENLDAP_LDAP_LIBRARY} ${OPENLDAP_LBER_LIBRARY}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args( OpenLDAP DEFAULT_MSG - OPENLDAP_INCLUDE_DIR OPENLDAP_LDAP_LIBRARY OPENLDAP_LBER_LIBRARY + OPENLDAP_INCLUDE_DIRS OPENLDAP_LDAP_LIBRARY OPENLDAP_LBER_LIBRARY ) -mark_as_advanced(OPENLDAP_INCLUDE_DIR OPENLDAP_LIBRARIES OPENLDAP_LDAP_LIBRARY OPENLDAP_LBER_LIBRARY) +mark_as_advanced(OPENLDAP_INCLUDE_DIRS OPENLDAP_LIBRARIES OPENLDAP_LDAP_LIBRARY OPENLDAP_LBER_LIBRARY) if(OPENLDAP_USE_STATIC_LIBS) set(CMAKE_FIND_LIBRARY_SUFFIXES ${_orig_CMAKE_FIND_LIBRARY_SUFFIXES}) diff --git a/cmake/find/ldap.cmake b/cmake/find/ldap.cmake index 230727819e4..0a753e80f08 100644 --- a/cmake/find/ldap.cmake +++ b/cmake/find/ldap.cmake @@ -54,7 +54,10 @@ if (ENABLE_LDAP) else () set (USE_INTERNAL_LDAP_LIBRARY 1) set (OPENLDAP_ROOT_DIR "${ClickHouse_SOURCE_DIR}/contrib/openldap") - set (OPENLDAP_INCLUDE_DIR "${ClickHouse_SOURCE_DIR}/contrib/openldap/include") + set (OPENLDAP_INCLUDE_DIRS + "${ClickHouse_SOURCE_DIR}/contrib/openldap-cmake/${_system_name}_${_system_processor}" + "${ClickHouse_SOURCE_DIR}/contrib/openldap/include" + ) # Below, 'ldap'/'ldap_r' and 'lber' will be resolved to # the targets defined in contrib/openldap-cmake/CMakeLists.txt if (OPENLDAP_USE_REENTRANT_LIBS) @@ -73,4 +76,4 @@ if (ENABLE_LDAP) endif () endif () -message (STATUS "Using ldap=${USE_LDAP}: ${OPENLDAP_INCLUDE_DIR} : ${OPENLDAP_LIBRARIES}") +message (STATUS "Using ldap=${USE_LDAP}: ${OPENLDAP_INCLUDE_DIRS} : ${OPENLDAP_LIBRARIES}") diff --git a/cmake/tools.cmake b/cmake/tools.cmake index d261b62eca3..95e00ad9951 100644 --- a/cmake/tools.cmake +++ b/cmake/tools.cmake @@ -22,7 +22,7 @@ elseif (COMPILER_CLANG) if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${APPLE_CLANG_MINIMUM_VERSION}) message (FATAL_ERROR "AppleClang compiler version must be at least ${APPLE_CLANG_MINIMUM_VERSION} (Xcode ${XCODE_MINIMUM_VERSION}).") elseif (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.0) - # char8_t is available staring (upstream vanilla) Clang 7, but prior to Clang 8, + # char8_t is available starting (upstream vanilla) Clang 7, but prior to Clang 8, # it is not enabled by -std=c++20 and can be enabled with an explicit -fchar8_t. set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fchar8_t") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fchar8_t") diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index d122188ad0b..402b7c9d8cf 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -109,7 +109,7 @@ if (USE_INTERNAL_SSL_LIBRARY) add_library(OpenSSL::SSL ALIAS ${OPENSSL_SSL_LIBRARY}) endif () -if (ENABLE_LDAP AND USE_INTERNAL_LDAP_LIBRARY) +if (USE_INTERNAL_LDAP_LIBRARY) add_subdirectory (openldap-cmake) endif () diff --git a/src/Access/LDAPClient.cpp b/src/Access/LDAPClient.cpp index d7f58b0ec50..8d27fca3276 100644 --- a/src/Access/LDAPClient.cpp +++ b/src/Access/LDAPClient.cpp @@ -2,6 +2,8 @@ #include #include +#include + namespace DB { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index baa0fbcb883..28dee92de02 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -325,7 +325,7 @@ if (OPENSSL_CRYPTO_LIBRARY) endif () if (USE_LDAP) - dbms_target_include_directories (SYSTEM BEFORE PRIVATE ${OPENLDAP_INCLUDE_DIR}) + dbms_target_include_directories (SYSTEM BEFORE PRIVATE ${OPENLDAP_INCLUDE_DIRS}) dbms_target_link_libraries (PRIVATE ${OPENLDAP_LIBRARIES}) endif () From 9fb0a95c750d163875c8fef473b33790678749b4 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 29 May 2020 16:14:42 +0400 Subject: [PATCH 007/143] Compilation fix: add missing "/include" Style fix --- cmake/find/ldap.cmake | 2 +- src/Access/ExternalAuthenticators.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmake/find/ldap.cmake b/cmake/find/ldap.cmake index 0a753e80f08..11594817e4f 100644 --- a/cmake/find/ldap.cmake +++ b/cmake/find/ldap.cmake @@ -55,7 +55,7 @@ if (ENABLE_LDAP) set (USE_INTERNAL_LDAP_LIBRARY 1) set (OPENLDAP_ROOT_DIR "${ClickHouse_SOURCE_DIR}/contrib/openldap") set (OPENLDAP_INCLUDE_DIRS - "${ClickHouse_SOURCE_DIR}/contrib/openldap-cmake/${_system_name}_${_system_processor}" + "${ClickHouse_SOURCE_DIR}/contrib/openldap-cmake/${_system_name}_${_system_processor}/include" "${ClickHouse_SOURCE_DIR}/contrib/openldap/include" ) # Below, 'ldap'/'ldap_r' and 'lber' will be resolved to diff --git a/src/Access/ExternalAuthenticators.h b/src/Access/ExternalAuthenticators.h index 1910243781f..dfd4e7061bd 100644 --- a/src/Access/ExternalAuthenticators.h +++ b/src/Access/ExternalAuthenticators.h @@ -8,8 +8,10 @@ #include -namespace Poco { +namespace Poco +{ class Logger; + namespace Util { class AbstractConfiguration; From 246900c1ace1d9b154b186f30f0d8732969db7c0 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 29 May 2020 18:33:50 +0400 Subject: [PATCH 008/143] Compilation fix --- src/Access/LDAPClient.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Access/LDAPClient.cpp b/src/Access/LDAPClient.cpp index 8d27fca3276..60bf49ff24e 100644 --- a/src/Access/LDAPClient.cpp +++ b/src/Access/LDAPClient.cpp @@ -4,6 +4,8 @@ #include +#include + namespace DB { @@ -133,7 +135,10 @@ int LDAPClient::openConnection(const bool graceful_bind_failure) } diag(ldap_set_option(handle, LDAP_OPT_RESTART, LDAP_OPT_ON)); + +#ifdef LDAP_OPT_KEEPCONN diag(ldap_set_option(handle, LDAP_OPT_KEEPCONN, LDAP_OPT_ON)); +#endif { ::timeval operation_timeout; From ec9cb953b46a1d85813a218a158e108f72f33d87 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 29 May 2020 23:26:41 +0400 Subject: [PATCH 009/143] Try to find and link with Cyrus SASL and GSSAPI too, if static OpenLDAP libraries are requested --- cmake/Modules/FindOpenLDAP.cmake | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/cmake/Modules/FindOpenLDAP.cmake b/cmake/Modules/FindOpenLDAP.cmake index ec559e9a7b5..6420678ad3c 100644 --- a/cmake/Modules/FindOpenLDAP.cmake +++ b/cmake/Modules/FindOpenLDAP.cmake @@ -7,8 +7,9 @@ # # Sets values of: # OPENLDAP_FOUND - TRUE if found -# OPENLDAP_INCLUDE_DIRS - list of paths to the include directories -# OPENLDAP_LIBRARIES - paths to the libldap and liblber libraries +# OPENLDAP_INCLUDE_DIRS - paths to the include directories +# OPENLDAP_LIBRARIES - paths to the libldap and liblber libraries; libsasl2 (Cyrus SASL) and libgssapi (GSSAPI) libraries +# will be listed here too, if found, if static OpenLDAP libraries are requested # OPENLDAP_LDAP_LIBRARY - paths to the libldap library # OPENLDAP_LBER_LIBRARY - paths to the liblber library # @@ -31,16 +32,34 @@ if(OPENLDAP_ROOT_DIR) find_path(OPENLDAP_INCLUDE_DIRS NAMES "ldap.h" "lber.h" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "include" NO_DEFAULT_PATH) find_library(OPENLDAP_LDAP_LIBRARY NAMES "ldap${_r_suffix}" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) find_library(OPENLDAP_LBER_LIBRARY NAMES "lber" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) + if(OPENLDAP_USE_STATIC_LIBS) + find_library(_cyrus_sasl_lib NAMES "sasl2" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) + find_library(_gssapi_lib NAMES "gssapi" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) + endif() else() find_path(OPENLDAP_INCLUDE_DIRS NAMES "ldap.h" "lber.h") find_library(OPENLDAP_LDAP_LIBRARY NAMES "ldap${_r_suffix}") find_library(OPENLDAP_LBER_LIBRARY NAMES "lber") + if(OPENLDAP_USE_STATIC_LIBS) + find_library(_cyrus_sasl_lib NAMES "sasl2") + find_library(_gssapi_lib NAMES "gssapi") + endif() endif() unset(_r_suffix) set(OPENLDAP_LIBRARIES ${OPENLDAP_LDAP_LIBRARY} ${OPENLDAP_LBER_LIBRARY}) +if(_cyrus_sasl_lib) + list(APPEND OPENLDAP_LIBRARIES ${_cyrus_sasl_lib}) + unset(_cyrus_sasl_lib) +endif() + +if(_gssapi_lib) + list(APPEND OPENLDAP_LIBRARIES ${_gssapi_lib}) + unset(_gssapi_lib) +endif() + include(FindPackageHandleStandardArgs) find_package_handle_standard_args( OpenLDAP DEFAULT_MSG From 165dc4e1094d3a757c51cb7579b1c0a9f4a29faf Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Sun, 31 May 2020 15:04:56 +0400 Subject: [PATCH 010/143] Disable system static OpenLDAP linking support (due to fPIC mismatch) --- cmake/Modules/FindOpenLDAP.cmake | 21 +-------------------- cmake/find/ldap.cmake | 13 +++++++++---- src/Access/LDAPClient.cpp | 4 ++-- 3 files changed, 12 insertions(+), 26 deletions(-) diff --git a/cmake/Modules/FindOpenLDAP.cmake b/cmake/Modules/FindOpenLDAP.cmake index 6420678ad3c..9c6262fa245 100644 --- a/cmake/Modules/FindOpenLDAP.cmake +++ b/cmake/Modules/FindOpenLDAP.cmake @@ -8,8 +8,7 @@ # Sets values of: # OPENLDAP_FOUND - TRUE if found # OPENLDAP_INCLUDE_DIRS - paths to the include directories -# OPENLDAP_LIBRARIES - paths to the libldap and liblber libraries; libsasl2 (Cyrus SASL) and libgssapi (GSSAPI) libraries -# will be listed here too, if found, if static OpenLDAP libraries are requested +# OPENLDAP_LIBRARIES - paths to the libldap and liblber libraries # OPENLDAP_LDAP_LIBRARY - paths to the libldap library # OPENLDAP_LBER_LIBRARY - paths to the liblber library # @@ -32,34 +31,16 @@ if(OPENLDAP_ROOT_DIR) find_path(OPENLDAP_INCLUDE_DIRS NAMES "ldap.h" "lber.h" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "include" NO_DEFAULT_PATH) find_library(OPENLDAP_LDAP_LIBRARY NAMES "ldap${_r_suffix}" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) find_library(OPENLDAP_LBER_LIBRARY NAMES "lber" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) - if(OPENLDAP_USE_STATIC_LIBS) - find_library(_cyrus_sasl_lib NAMES "sasl2" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) - find_library(_gssapi_lib NAMES "gssapi" PATHS "${OPENLDAP_ROOT_DIR}" PATH_SUFFIXES "lib" NO_DEFAULT_PATH) - endif() else() find_path(OPENLDAP_INCLUDE_DIRS NAMES "ldap.h" "lber.h") find_library(OPENLDAP_LDAP_LIBRARY NAMES "ldap${_r_suffix}") find_library(OPENLDAP_LBER_LIBRARY NAMES "lber") - if(OPENLDAP_USE_STATIC_LIBS) - find_library(_cyrus_sasl_lib NAMES "sasl2") - find_library(_gssapi_lib NAMES "gssapi") - endif() endif() unset(_r_suffix) set(OPENLDAP_LIBRARIES ${OPENLDAP_LDAP_LIBRARY} ${OPENLDAP_LBER_LIBRARY}) -if(_cyrus_sasl_lib) - list(APPEND OPENLDAP_LIBRARIES ${_cyrus_sasl_lib}) - unset(_cyrus_sasl_lib) -endif() - -if(_gssapi_lib) - list(APPEND OPENLDAP_LIBRARIES ${_gssapi_lib}) - unset(_gssapi_lib) -endif() - include(FindPackageHandleStandardArgs) find_package_handle_standard_args( OpenLDAP DEFAULT_MSG diff --git a/cmake/find/ldap.cmake b/cmake/find/ldap.cmake index 11594817e4f..99c9007d6b5 100644 --- a/cmake/find/ldap.cmake +++ b/cmake/find/ldap.cmake @@ -16,11 +16,16 @@ if (ENABLE_LDAP) set (OPENLDAP_USE_REENTRANT_LIBS 1) if (NOT USE_INTERNAL_LDAP_LIBRARY) - if (APPLE AND NOT OPENLDAP_ROOT_DIR) - set (OPENLDAP_ROOT_DIR "/usr/local/opt/openldap") - endif () + if (OPENLDAP_USE_STATIC_LIBS) + message (WARNING "Unable to use external static OpenLDAP libraries, falling back to the bundled version.") + set (USE_INTERNAL_LDAP_LIBRARY 1) + else () + if (APPLE AND NOT OPENLDAP_ROOT_DIR) + set (OPENLDAP_ROOT_DIR "/usr/local/opt/openldap") + endif () - find_package (OpenLDAP) + find_package (OpenLDAP) + endif () endif () if (NOT OPENLDAP_FOUND AND NOT MISSING_INTERNAL_LDAP_LIBRARY) diff --git a/src/Access/LDAPClient.cpp b/src/Access/LDAPClient.cpp index 60bf49ff24e..fc6ee697468 100644 --- a/src/Access/LDAPClient.cpp +++ b/src/Access/LDAPClient.cpp @@ -225,11 +225,11 @@ bool LDAPSimpleAuthClient::check() if (params.user.empty()) throw Exception("LDAP authentication of a user with an empty name is not allowed", ErrorCodes::BAD_ARGUMENTS); + SCOPE_EXIT({ closeConnection(); }); + const bool graceful_bind_failure = true; const auto rc = openConnection(graceful_bind_failure); - SCOPE_EXIT({ closeConnection(); }); - switch (rc) { case LDAP_SUCCESS: From e41062172af6a6f7e6d600892384a8b127615f0a Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Tue, 2 Jun 2020 13:35:40 +0400 Subject: [PATCH 011/143] Stylistic changes/renaming --- src/Parsers/ASTCreateUserQuery.cpp | 14 +++++++------- src/Parsers/ParserCreateUserQuery.cpp | 14 +++++++++----- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Parsers/ASTCreateUserQuery.cpp b/src/Parsers/ASTCreateUserQuery.cpp index 087c8160bad..8782c112060 100644 --- a/src/Parsers/ASTCreateUserQuery.cpp +++ b/src/Parsers/ASTCreateUserQuery.cpp @@ -32,7 +32,7 @@ namespace } String authentication_type_name = Authentication::TypeInfo::get(authentication_type).name; - std::optional password; + std::optional by_value; if (show_password || authentication_type == Authentication::LDAP_SERVER) { @@ -40,24 +40,24 @@ namespace { case Authentication::PLAINTEXT_PASSWORD: { - password = authentication.getPassword(); + by_value = authentication.getPassword(); break; } case Authentication::SHA256_PASSWORD: { authentication_type_name = "sha256_hash"; - password = authentication.getPasswordHashHex(); + by_value = authentication.getPasswordHashHex(); break; } case Authentication::DOUBLE_SHA1_PASSWORD: { authentication_type_name = "double_sha1_hash"; - password = authentication.getPasswordHashHex(); + by_value = authentication.getPasswordHashHex(); break; } case Authentication::LDAP_SERVER: { - password = authentication.getServerName(); + by_value = authentication.getServerName(); break; } @@ -69,8 +69,8 @@ namespace settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " IDENTIFIED WITH " << authentication_type_name << (settings.hilite ? IAST::hilite_none : ""); - if (password) - settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " BY " << quoteString(*password); + if (by_value) + settings.ostr << (settings.hilite ? IAST::hilite_keyword : "") << " BY " << quoteString(*by_value); } diff --git a/src/Parsers/ParserCreateUserQuery.cpp b/src/Parsers/ParserCreateUserQuery.cpp index 1317f18ca65..00288709cd8 100644 --- a/src/Parsers/ParserCreateUserQuery.cpp +++ b/src/Parsers/ParserCreateUserQuery.cpp @@ -51,7 +51,7 @@ namespace std::optional type; bool expect_password = false; bool expect_hash = false; - bool expect_server = false; + bool expect_server_name = false; if (ParserKeyword{"WITH"}.ignore(pos, expected)) { @@ -60,8 +60,12 @@ namespace if (ParserKeyword{Authentication::TypeInfo::get(check_type).raw_name}.ignore(pos, expected)) { type = check_type; - expect_password = (check_type != Authentication::NO_PASSWORD && check_type != Authentication::LDAP_SERVER); - expect_server = (check_type == Authentication::LDAP_SERVER); + + if (check_type == Authentication::LDAP_SERVER) + expect_server_name = true; + else if (check_type != Authentication::NO_PASSWORD) + expect_password = true; + break; } } @@ -90,7 +94,7 @@ namespace } String value; - if (expect_password || expect_hash || expect_server) + if (expect_password || expect_hash || expect_server_name) { ASTPtr ast; if (!ParserKeyword{"BY"}.ignore(pos, expected) || !ParserStringLiteral{}.parse(pos, ast, expected)) @@ -104,7 +108,7 @@ namespace authentication->setPassword(value); else if (expect_hash) authentication->setPasswordHashHex(value); - else if (expect_server) + else if (expect_server_name) authentication->setServerName(value); return true; From 6ff0550e4eb4764edc20e860c5b07c273e4d4a84 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Tue, 2 Jun 2020 13:37:02 +0400 Subject: [PATCH 012/143] Move parseExternalAuthenticators functionality into the c-tor of ExternalAuthenticators --- src/Access/AccessControlManager.cpp | 2 +- src/Access/ExternalAuthenticators.cpp | 12 +++++------- src/Access/ExternalAuthenticators.h | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Access/AccessControlManager.cpp b/src/Access/AccessControlManager.cpp index 07002971734..940ddc5dcdc 100644 --- a/src/Access/AccessControlManager.cpp +++ b/src/Access/AccessControlManager.cpp @@ -101,7 +101,7 @@ void AccessControlManager::setLocalDirectory(const String & directory_path) void AccessControlManager::setUsersConfig(const Poco::Util::AbstractConfiguration & users_config) { - external_authenticators = parseExternalAuthenticators(users_config, getLogger()); + external_authenticators = std::make_unique(users_config, getLogger()); auto & users_config_access_storage = dynamic_cast(getStorageByIndex(USERS_CONFIG_ACCESS_STORAGE_INDEX)); users_config_access_storage.setConfiguration(users_config); } diff --git a/src/Access/ExternalAuthenticators.cpp b/src/Access/ExternalAuthenticators.cpp index 97f2f24a72e..5d46f5e96ee 100644 --- a/src/Access/ExternalAuthenticators.cpp +++ b/src/Access/ExternalAuthenticators.cpp @@ -115,6 +115,11 @@ void parseAndAddLDAPServers(ExternalAuthenticators & external_authenticators, co } +ExternalAuthenticators::ExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) +{ + parseAndAddLDAPServers(*this, config, log); +} + void ExternalAuthenticators::setLDAPServerParams(const String & server, const LDAPServerParams & params) { std::scoped_lock lock(mutex); @@ -131,11 +136,4 @@ LDAPServerParams ExternalAuthenticators::getLDAPServerParams(const String & serv return it->second; } -std::unique_ptr parseExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) -{ - auto external_authenticators = std::make_unique(); - parseAndAddLDAPServers(*external_authenticators, config, log); - return external_authenticators; -} - } diff --git a/src/Access/ExternalAuthenticators.h b/src/Access/ExternalAuthenticators.h index dfd4e7061bd..50d9e68f91f 100644 --- a/src/Access/ExternalAuthenticators.h +++ b/src/Access/ExternalAuthenticators.h @@ -25,6 +25,8 @@ namespace DB class ExternalAuthenticators { public: + explicit ExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log); + void setLDAPServerParams(const String & server, const LDAPServerParams & params); LDAPServerParams getLDAPServerParams(const String & server) const; @@ -33,6 +35,4 @@ private: std::map ldap_server_params; }; -std::unique_ptr parseExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log); - } From 920e792f3392f295a44fba41040c3684c76e46ab Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Tue, 2 Jun 2020 13:38:20 +0400 Subject: [PATCH 013/143] Add USE_LDAP to table system.build_options --- src/Storages/System/StorageSystemBuildOptions.generated.cpp.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Storages/System/StorageSystemBuildOptions.generated.cpp.in b/src/Storages/System/StorageSystemBuildOptions.generated.cpp.in index 9f73c00d22b..275342996ef 100644 --- a/src/Storages/System/StorageSystemBuildOptions.generated.cpp.in +++ b/src/Storages/System/StorageSystemBuildOptions.generated.cpp.in @@ -54,6 +54,7 @@ const char * auto_config_build[] "USE_HYPERSCAN", "@USE_HYPERSCAN@", "USE_SIMDJSON", "@USE_SIMDJSON@", "USE_GRPC", "@USE_GRPC@", + "USE_LDAP", "@USE_LDAP@", nullptr, nullptr }; From e75bb335e304ffe9ef0f90491f5381c7d6a40471 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Tue, 2 Jun 2020 13:40:32 +0400 Subject: [PATCH 014/143] Fix: set auth_params column value for each row, by default to "{}" empty JSON object --- src/Storages/System/StorageSystemUsers.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Storages/System/StorageSystemUsers.cpp b/src/Storages/System/StorageSystemUsers.cpp index a1e7eba7232..604831df425 100644 --- a/src/Storages/System/StorageSystemUsers.cpp +++ b/src/Storages/System/StorageSystemUsers.cpp @@ -90,10 +90,11 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, const Context & column_storage.insertData(storage_name.data(), storage_name.length()); column_auth_type.push_back(static_cast(authentication.getType())); - if (authentication.getType() == Authentication::Type::LDAP_SERVER) { Poco::JSON::Object auth_params_json; - auth_params_json.set("server", authentication.getServerName()); + + if (authentication.getType() == Authentication::Type::LDAP_SERVER) + auth_params_json.set("server", authentication.getServerName()); std::ostringstream oss; Poco::JSON::Stringifier::stringify(auth_params_json, oss); From b7caa154e29beacdf1d2b6bad3c21573b7e7fb58 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 3 Jun 2020 00:37:14 +0400 Subject: [PATCH 015/143] Add ARCADIA_BUILD check --- src/Access/LDAPClient.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Access/LDAPClient.h b/src/Access/LDAPClient.h index a07dc93f4b1..d166a59aac2 100644 --- a/src/Access/LDAPClient.h +++ b/src/Access/LDAPClient.h @@ -1,6 +1,6 @@ #pragma once -#if __has_include("config_core.h") +#if !defined(ARCADIA_BUILD) && __has_include("config_core.h") #include "config_core.h" #endif From 979fa13b269cde9842d1409b955b818e29ff172d Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 3 Jun 2020 00:38:00 +0400 Subject: [PATCH 016/143] Simplify condition --- src/Server/MySQLHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Server/MySQLHandler.cpp b/src/Server/MySQLHandler.cpp index a947a322488..c5107b22e4d 100644 --- a/src/Server/MySQLHandler.cpp +++ b/src/Server/MySQLHandler.cpp @@ -222,7 +222,7 @@ void MySQLHandler::authenticate(const String & user_name, const String & auth_pl // For compatibility with JavaScript MySQL client, Native41 authentication plugin is used when possible (if password is specified using double SHA1). Otherwise SHA256 plugin is used. auto user = connection_context.getAccessControlManager().read(user_name); const DB::Authentication::Type user_auth_type = user->authentication.getType(); - if (user_auth_type != DB::Authentication::LDAP_SERVER && user_auth_type != DB::Authentication::DOUBLE_SHA1_PASSWORD && user_auth_type != DB::Authentication::PLAINTEXT_PASSWORD && user_auth_type != DB::Authentication::NO_PASSWORD) + if (user_auth_type == DB::Authentication::SHA256_PASSWORD) { authPluginSSL(); } From c427524bc81f90e061cbe32c6d1b6386cd3823e4 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 3 Jun 2020 01:02:31 +0400 Subject: [PATCH 017/143] Simplefy ExternalAuthenticators exposure to isCorrectPassword() --- src/Access/ContextAccess.cpp | 4 ++-- src/Access/ContextAccess.h | 2 +- src/Interpreters/Context.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Access/ContextAccess.cpp b/src/Access/ContextAccess.cpp index 09f613b6851..9e02ab5be48 100644 --- a/src/Access/ContextAccess.cpp +++ b/src/Access/ContextAccess.cpp @@ -176,12 +176,12 @@ void ContextAccess::setRolesInfo(const std::shared_ptr & } -bool ContextAccess::isCorrectPassword(const String & password, const ExternalAuthenticators & external_authenticators) const +bool ContextAccess::isCorrectPassword(const String & password) const { std::lock_guard lock{mutex}; if (!user) return false; - return user->authentication.isCorrectPassword(password, user_name, external_authenticators); + return user->authentication.isCorrectPassword(password, user_name, manager->getExternalAuthenticators()); } bool ContextAccess::isClientHostAllowed() const diff --git a/src/Access/ContextAccess.h b/src/Access/ContextAccess.h index 062ab37e414..19a799e49d4 100644 --- a/src/Access/ContextAccess.h +++ b/src/Access/ContextAccess.h @@ -64,7 +64,7 @@ public: String getUserName() const; /// External authenticators may be used by only some of the authentication mechanisms. - bool isCorrectPassword(const String & password, const ExternalAuthenticators & external_authenticators) const; + bool isCorrectPassword(const String & password) const; bool isClientHostAllowed() const; /// Returns information about current and enabled roles. diff --git a/src/Interpreters/Context.cpp b/src/Interpreters/Context.cpp index 8212513650a..5e2f4ecadab 100644 --- a/src/Interpreters/Context.cpp +++ b/src/Interpreters/Context.cpp @@ -665,7 +665,7 @@ void Context::setUser(const String & name, const String & password, const Poco:: if (new_user_id) { new_access = getAccessControlManager().getContextAccess(*new_user_id, {}, true, settings, current_database, client_info); - if (!new_access->isClientHostAllowed() || !new_access->isCorrectPassword(password, getAccessControlManager().getExternalAuthenticators())) + if (!new_access->isClientHostAllowed() || !new_access->isCorrectPassword(password)) { new_user_id = {}; new_access = nullptr; From 48f3d4094a02fd094c88d40c4c8dfbc718633122 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 3 Jun 2020 01:06:44 +0400 Subject: [PATCH 018/143] Remove irrelevant stuff --- src/Access/ContextAccess.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Access/ContextAccess.h b/src/Access/ContextAccess.h index 19a799e49d4..27bb29a878c 100644 --- a/src/Access/ContextAccess.h +++ b/src/Access/ContextAccess.h @@ -26,7 +26,6 @@ struct QuotaUsage; struct Settings; class SettingsConstraints; class AccessControlManager; -class ExternalAuthenticators; class IAST; using ASTPtr = std::shared_ptr; @@ -63,7 +62,6 @@ public: UserPtr getUser() const; String getUserName() const; - /// External authenticators may be used by only some of the authentication mechanisms. bool isCorrectPassword(const String & password) const; bool isClientHostAllowed() const; From ca1381d47560a9ad1883f2f7b712b64ffe32cf19 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 3 Jun 2020 01:17:59 +0400 Subject: [PATCH 019/143] Write empty json in more efficient way --- src/Storages/System/StorageSystemUsers.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Storages/System/StorageSystemUsers.cpp b/src/Storages/System/StorageSystemUsers.cpp index 604831df425..780542677c9 100644 --- a/src/Storages/System/StorageSystemUsers.cpp +++ b/src/Storages/System/StorageSystemUsers.cpp @@ -90,11 +90,11 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, const Context & column_storage.insertData(storage_name.data(), storage_name.length()); column_auth_type.push_back(static_cast(authentication.getType())); + if (authentication.getType() == Authentication::Type::LDAP_SERVER) { Poco::JSON::Object auth_params_json; - if (authentication.getType() == Authentication::Type::LDAP_SERVER) - auth_params_json.set("server", authentication.getServerName()); + auth_params_json.set("server", authentication.getServerName()); std::ostringstream oss; Poco::JSON::Stringifier::stringify(auth_params_json, oss); @@ -102,6 +102,11 @@ void StorageSystemUsers::fillData(MutableColumns & res_columns, const Context & column_auth_params.insertData(str.data(), str.size()); } + else + { + static constexpr std::string_view empty_json{"{}"}; + column_auth_params.insertData(empty_json.data(), empty_json.length()); + } if (allowed_hosts.containsAnyHost()) { From 2f2275c3ba5090031c506e1a93bd72d2cdbdc3d5 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 3 Jun 2020 15:16:58 +0400 Subject: [PATCH 020/143] Add "-D ENABLE_LDAP=0" --- utils/ci/jobs/quick-build/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/ci/jobs/quick-build/run.sh b/utils/ci/jobs/quick-build/run.sh index 56f0950c717..013f31ca46d 100755 --- a/utils/ci/jobs/quick-build/run.sh +++ b/utils/ci/jobs/quick-build/run.sh @@ -21,7 +21,7 @@ BUILD_TARGETS=clickhouse BUILD_TYPE=Debug ENABLE_EMBEDDED_COMPILER=0 -CMAKE_FLAGS="-D CMAKE_C_FLAGS_ADD=-g0 -D CMAKE_CXX_FLAGS_ADD=-g0 -D ENABLE_JEMALLOC=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_UNWIND=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_REDIS=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_ODBC=0 -D ENABLE_MYSQL=0 -D ENABLE_SSL=0 -D ENABLE_POCO_NETSSL=0" +CMAKE_FLAGS="-D CMAKE_C_FLAGS_ADD=-g0 -D CMAKE_CXX_FLAGS_ADD=-g0 -D ENABLE_JEMALLOC=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_UNWIND=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_REDIS=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_ODBC=0 -D ENABLE_MYSQL=0 -D ENABLE_SSL=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_LDAP=0" [[ $(uname) == "FreeBSD" ]] && COMPILER_PACKAGE_VERSION=devel && export COMPILER_PATH=/usr/local/bin From b28def8f4ce2be0a57cfff4b719e5344187a3299 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 3 Jun 2020 15:20:53 +0400 Subject: [PATCH 021/143] Stylistic changes --- src/Access/LDAPClient.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Access/LDAPClient.h b/src/Access/LDAPClient.h index d166a59aac2..5aad2ed3061 100644 --- a/src/Access/LDAPClient.h +++ b/src/Access/LDAPClient.h @@ -1,17 +1,17 @@ #pragma once -#if !defined(ARCADIA_BUILD) && __has_include("config_core.h") -#include "config_core.h" +#if !defined(ARCADIA_BUILD) +# include "config_core.h" #endif #include #include #if USE_LDAP -#include -#define MAYBE_NORETURN +# include +# define MAYBE_NORETURN #else -#define MAYBE_NORETURN [[noreturn]] +# define MAYBE_NORETURN [[noreturn]] #endif From f44449f6d6e0829ca689176ad60b342f2269de3e Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 3 Jun 2020 17:31:53 +0400 Subject: [PATCH 022/143] Fix the test --- tests/integration/test_grant_and_revoke/test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/test_grant_and_revoke/test.py b/tests/integration/test_grant_and_revoke/test.py index 7054ce28e59..f01f61f4e22 100644 --- a/tests/integration/test_grant_and_revoke/test.py +++ b/tests/integration/test_grant_and_revoke/test.py @@ -156,9 +156,9 @@ def test_introspection(): assert instance.query("SHOW ENABLED ROLES", user='B') == TSV([[ "R2", 1, 1, 1 ]]) assert instance.query("SELECT name, storage, auth_type, auth_params, host_ip, host_names, host_names_regexp, host_names_like, default_roles_all, default_roles_list, default_roles_except from system.users WHERE name IN ('A', 'B') ORDER BY name") ==\ - TSV([[ "A", "disk", "no_password", "[]", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ], - [ "B", "disk", "no_password", "[]", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ]]) - + TSV([[ "A", "disk", "no_password", "{}", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ], + [ "B", "disk", "no_password", "{}", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ]]) + assert instance.query("SELECT name, storage from system.roles WHERE name IN ('R1', 'R2') ORDER BY name") ==\ TSV([[ "R1", "disk" ], [ "R2", "disk" ]]) From 0197627f3fc989b533a06ea195a349faf3a38bd8 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 3 Jun 2020 22:52:12 +0400 Subject: [PATCH 023/143] Added checks for empty server name --- src/Access/ExternalAuthenticators.cpp | 3 +++ src/Access/UsersConfigAccessStorage.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/Access/ExternalAuthenticators.cpp b/src/Access/ExternalAuthenticators.cpp index 5d46f5e96ee..8d0487bfd31 100644 --- a/src/Access/ExternalAuthenticators.cpp +++ b/src/Access/ExternalAuthenticators.cpp @@ -18,6 +18,9 @@ namespace auto parseLDAPServer(const Poco::Util::AbstractConfiguration & config, const String & ldap_server_name) { + if (ldap_server_name.empty()) + throw Exception("LDAP server name cannot be empty", ErrorCodes::BAD_ARGUMENTS); + LDAPServerParams params; const String ldap_server_config = "ldap_servers." + ldap_server_name; diff --git a/src/Access/UsersConfigAccessStorage.cpp b/src/Access/UsersConfigAccessStorage.cpp index 38925142460..4560c3f41ba 100644 --- a/src/Access/UsersConfigAccessStorage.cpp +++ b/src/Access/UsersConfigAccessStorage.cpp @@ -88,6 +88,8 @@ namespace throw Exception("Missing mandatory 'server' in 'ldap', with LDAP server name, for user " + user_name + ".", ErrorCodes::BAD_ARGUMENTS); const auto ldap_server_name = config.getString(user_config + ".ldap.server"); + if (ldap_server_name.empty()) + throw Exception("LDAP server name cannot be empty for user " + user_name + ".", ErrorCodes::BAD_ARGUMENTS); user->authentication = Authentication{Authentication::LDAP_SERVER}; user->authentication.setServerName(ldap_server_name); From 848330b37a08337a425eac29f8ef381daa2e6ee1 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Thu, 11 Jun 2020 02:48:15 +0400 Subject: [PATCH 024/143] Expect in main config.xml --- programs/local/LocalServer.cpp | 3 +++ programs/server/Server.cpp | 3 +++ programs/server/config.xml | 32 +++++++++++++++++++++++++++ programs/server/users.xml | 34 +---------------------------- src/Access/AccessControlManager.cpp | 7 +++++- src/Access/AccessControlManager.h | 1 + src/Interpreters/Context.cpp | 6 +++++ src/Interpreters/Context.h | 3 +++ 8 files changed, 55 insertions(+), 34 deletions(-) diff --git a/programs/local/LocalServer.cpp b/programs/local/LocalServer.cpp index 8ce03ac0867..1b1e5c2debb 100644 --- a/programs/local/LocalServer.cpp +++ b/programs/local/LocalServer.cpp @@ -176,6 +176,9 @@ try /// Skip networking + /// Sets external authenticators config (LDAP). + context->setExternalAuthenticatorsConfig(config()); + setupUsers(); /// Limit on total number of concurrently executing queries. diff --git a/programs/server/Server.cpp b/programs/server/Server.cpp index e587e134075..18b87d2a704 100644 --- a/programs/server/Server.cpp +++ b/programs/server/Server.cpp @@ -528,6 +528,9 @@ int Server::main(const std::vector & /*args*/) if (!access_control_local_path.empty()) global_context->getAccessControlManager().setLocalDirectory(access_control_local_path); + /// Sets external authenticators config (LDAP). + global_context->setExternalAuthenticatorsConfig(config()); + /// Limit on total number of concurrently executed queries. global_context->getProcessList().setMaxSize(config().getInt("max_concurrent_queries", 0)); diff --git a/programs/server/config.xml b/programs/server/config.xml index 21605edeb36..5086e5e557c 100644 --- a/programs/server/config.xml +++ b/programs/server/config.xml @@ -192,6 +192,38 @@ /var/lib/clickhouse/access/ + + + + + users.xml diff --git a/programs/server/users.xml b/programs/server/users.xml index 286c065722e..838b46e6938 100644 --- a/programs/server/users.xml +++ b/programs/server/users.xml @@ -27,38 +27,6 @@ - - - - - @@ -76,7 +44,7 @@ If you want to specify double SHA1, place it in 'password_double_sha1_hex' element. Example: e395796d6546b1b65db9d665cd43f0e858dd4303 - If you want to specify a previously defined LDAP server (see 'ldap_servers' above) for authentication, place its name in 'server' element inside 'ldap' element. + If you want to specify a previously defined LDAP server (see 'ldap_servers' in main config) for authentication, place its name in 'server' element inside 'ldap' element. Example: my_ldap_server How to generate decent password: diff --git a/src/Access/AccessControlManager.cpp b/src/Access/AccessControlManager.cpp index 940ddc5dcdc..5d02eca2bc8 100644 --- a/src/Access/AccessControlManager.cpp +++ b/src/Access/AccessControlManager.cpp @@ -99,9 +99,14 @@ void AccessControlManager::setLocalDirectory(const String & directory_path) } +void AccessControlManager::setExternalAuthenticatorsConfig(const Poco::Util::AbstractConfiguration & config) +{ + external_authenticators = std::make_unique(config, getLogger()); +} + + void AccessControlManager::setUsersConfig(const Poco::Util::AbstractConfiguration & users_config) { - external_authenticators = std::make_unique(users_config, getLogger()); auto & users_config_access_storage = dynamic_cast(getStorageByIndex(USERS_CONFIG_ACCESS_STORAGE_INDEX)); users_config_access_storage.setConfiguration(users_config); } diff --git a/src/Access/AccessControlManager.h b/src/Access/AccessControlManager.h index 4ef971dca65..267f92a2aa4 100644 --- a/src/Access/AccessControlManager.h +++ b/src/Access/AccessControlManager.h @@ -48,6 +48,7 @@ public: ~AccessControlManager(); void setLocalDirectory(const String & directory); + void setExternalAuthenticatorsConfig(const Poco::Util::AbstractConfiguration & config); void setUsersConfig(const Poco::Util::AbstractConfiguration & users_config); void setDefaultProfileName(const String & default_profile_name); diff --git a/src/Interpreters/Context.cpp b/src/Interpreters/Context.cpp index 5e2f4ecadab..b3e5e348cb9 100644 --- a/src/Interpreters/Context.cpp +++ b/src/Interpreters/Context.cpp @@ -618,6 +618,7 @@ void Context::setConfig(const ConfigurationPtr & config) { auto lock = getLock(); shared->config = config; + shared->access_control_manager.setExternalAuthenticatorsConfig(*shared->config); } const Poco::Util::AbstractConfiguration & Context::getConfigRef() const @@ -637,6 +638,11 @@ const AccessControlManager & Context::getAccessControlManager() const return shared->access_control_manager; } +void Context::setExternalAuthenticatorsConfig(const Poco::Util::AbstractConfiguration & config) +{ + auto lock = getLock(); + shared->access_control_manager.setExternalAuthenticatorsConfig(config); +} void Context::setUsersConfig(const ConfigurationPtr & config) { diff --git a/src/Interpreters/Context.h b/src/Interpreters/Context.h index 864468c0663..10f9d688136 100644 --- a/src/Interpreters/Context.h +++ b/src/Interpreters/Context.h @@ -243,6 +243,9 @@ public: AccessControlManager & getAccessControlManager(); const AccessControlManager & getAccessControlManager() const; + /// Sets external authenticators config (LDAP). + void setExternalAuthenticatorsConfig(const Poco::Util::AbstractConfiguration & config); + /** Take the list of users, quotas and configuration profiles from this config. * The list of users is completely replaced. * The accumulated quota values are not reset if the quota is not deleted. From 04f222f85b0e240c3511df68beab63f423379a89 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 12 Jun 2020 16:48:00 +0400 Subject: [PATCH 025/143] Tell OpenLDAP too create a new SSL/TLS context for each connection --- src/Access/LDAPClient.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Access/LDAPClient.cpp b/src/Access/LDAPClient.cpp index fc6ee697468..b538c06c9ea 100644 --- a/src/Access/LDAPClient.cpp +++ b/src/Access/LDAPClient.cpp @@ -182,6 +182,13 @@ int LDAPClient::openConnection(const bool graceful_bind_failure) if (!params.ca_cert_file.empty()) diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTFILE, params.ca_cert_file.c_str())); +#ifdef LDAP_OPT_X_TLS_NEWCTX + { + const int i_am_a_server = 0; + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_NEWCTX, &i_am_a_server)); + } +#endif + if (params.enable_tls == LDAPServerParams::TLSEnable::YES_STARTTLS) diag(ldap_start_tls_s(handle, nullptr, nullptr)); From 276fcd8903ff8ec5bbd394d7221e65fbfa005bfe Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 12 Jun 2020 21:59:47 +0400 Subject: [PATCH 026/143] Add/rename parameters that control TLS --- programs/server/config.xml | 25 +++++++--- src/Access/ExternalAuthenticators.cpp | 70 +++++++++++++++++++-------- src/Access/LDAPClient.cpp | 58 ++++++++++++++++++---- src/Access/LDAPParams.h | 21 ++++++-- 4 files changed, 134 insertions(+), 40 deletions(-) diff --git a/programs/server/config.xml b/programs/server/config.xml index 372f418c812..f43ecad9a78 100644 --- a/programs/server/config.xml +++ b/programs/server/config.xml @@ -209,20 +209,29 @@ Specify 'no' for plain text (ldap://) protocol (not recommended). Specify 'yes' for LDAP over SSL/TLS (ldaps://) protocol (recommended, the default). Specify 'starttls' for legacy StartTLS protocol (plain text (ldap://) protocol, upgraded to TLS). - tls_cert_verify - TLS peer certificate verification behavior. - Accepted values are: never, allow, try, demand. - ca_cert_dir - path to CA certificates directory. - ca_cert_file - path to CA certificate file. - Example: + tls_minimum_protocol_version - the minimum protocol version of SSL/TLS. + Accepted values are: 'ssl2', 'ssl3', 'tls1.0', 'tls1.1', 'tls1.2' (the default). + tls_require_cert - SSL/TLS peer certificate verification behavior. + Accepted values are: 'never', 'allow', 'try', 'demand' (the default). + tls_cert_file - path to certificate file. + tls_key_file - path to certificate key file. + tls_ca_cert_file - path to CA certificate file. + tls_ca_cert_dir - path to the directory containing CA certificates. + tls_cipher_suite - allowed cipher suite. + Example: localhost 636 cn= , ou=users, dc=example, dc=com yes - demand - /path/to/ca_cert_dir - /path/to/ca_cert_file + tls1.2 + demand + /path/to/tls_cert_file + /path/to/tls_key_file + /path/to/tls_ca_cert_file + /path/to/tls_ca_cert_dir + SECURE256:+SECURE128:-VERS-TLS-ALL:+VERS-TLS1.2:-RSA:-DHE-DSS:-CAMELLIA-128-CBC:-CAMELLIA-256-CBC --> diff --git a/src/Access/ExternalAuthenticators.cpp b/src/Access/ExternalAuthenticators.cpp index 8d0487bfd31..fcb7317a52d 100644 --- a/src/Access/ExternalAuthenticators.cpp +++ b/src/Access/ExternalAuthenticators.cpp @@ -30,9 +30,13 @@ auto parseLDAPServer(const Poco::Util::AbstractConfiguration & config, const Str const bool has_auth_dn_prefix = config.has(ldap_server_config + ".auth_dn_prefix"); const bool has_auth_dn_suffix = config.has(ldap_server_config + ".auth_dn_suffix"); const bool has_enable_tls = config.has(ldap_server_config + ".enable_tls"); - const bool has_tls_cert_verify = config.has(ldap_server_config + ".tls_cert_verify"); - const bool has_ca_cert_dir = config.has(ldap_server_config + ".ca_cert_dir"); - const bool has_ca_cert_file = config.has(ldap_server_config + ".ca_cert_file"); + const bool has_tls_minimum_protocol_version = config.has(ldap_server_config + ".tls_minimum_protocol_version"); + const bool has_tls_require_cert = config.has(ldap_server_config + ".tls_require_cert"); + const bool has_tls_cert_file = config.has(ldap_server_config + ".tls_cert_file"); + const bool has_tls_key_file = config.has(ldap_server_config + ".tls_key_file"); + const bool has_tls_ca_cert_file = config.has(ldap_server_config + ".tls_ca_cert_file"); + const bool has_tls_ca_cert_dir = config.has(ldap_server_config + ".tls_ca_cert_dir"); + const bool has_tls_cipher_suite = config.has(ldap_server_config + ".tls_cipher_suite"); if (!has_host) throw Exception("Missing 'host' entry", ErrorCodes::BAD_ARGUMENTS); @@ -61,28 +65,56 @@ auto parseLDAPServer(const Poco::Util::AbstractConfiguration & config, const Str params.enable_tls = LDAPServerParams::TLSEnable::NO; } - if (has_tls_cert_verify) + if (has_tls_minimum_protocol_version) { - String tls_cert_verify_lc_str = config.getString(ldap_server_config + ".tls_cert_verify"); - boost::to_lower(tls_cert_verify_lc_str); + String tls_minimum_protocol_version_lc_str = config.getString(ldap_server_config + ".tls_minimum_protocol_version"); + boost::to_lower(tls_minimum_protocol_version_lc_str); - if (tls_cert_verify_lc_str == "never") - params.tls_cert_verify = LDAPServerParams::TLSCertVerify::NEVER; - else if (tls_cert_verify_lc_str == "allow") - params.tls_cert_verify = LDAPServerParams::TLSCertVerify::ALLOW; - else if (tls_cert_verify_lc_str == "try") - params.tls_cert_verify = LDAPServerParams::TLSCertVerify::TRY; - else if (tls_cert_verify_lc_str == "demand") - params.tls_cert_verify = LDAPServerParams::TLSCertVerify::DEMAND; + if (tls_minimum_protocol_version_lc_str == "ssl2") + params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::SSL2; + else if (tls_minimum_protocol_version_lc_str == "ssl3") + params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::SSL3; + else if (tls_minimum_protocol_version_lc_str == "tls1.0") + params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::TLS1_0; + else if (tls_minimum_protocol_version_lc_str == "tls1.1") + params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::TLS1_1; + else if (tls_minimum_protocol_version_lc_str == "tls1.2") + params.tls_minimum_protocol_version = LDAPServerParams::TLSProtocolVersion::TLS1_2; else - throw Exception("Bad value for 'tls_cert_verify' entry, allowed values are: 'never', 'allow', 'try', 'demand'", ErrorCodes::BAD_ARGUMENTS); + throw Exception("Bad value for 'tls_minimum_protocol_version' entry, allowed values are: 'ssl2', 'ssl3', 'tls1.0', 'tls1.1', 'tls1.2'", ErrorCodes::BAD_ARGUMENTS); } - if (has_ca_cert_dir) - params.ca_cert_dir = config.getString(ldap_server_config + ".ca_cert_dir"); + if (has_tls_require_cert) + { + String tls_require_cert_lc_str = config.getString(ldap_server_config + ".tls_require_cert"); + boost::to_lower(tls_require_cert_lc_str); - if (has_ca_cert_file) - params.ca_cert_file = config.getString(ldap_server_config + ".ca_cert_file"); + if (tls_require_cert_lc_str == "never") + params.tls_require_cert = LDAPServerParams::TLSRequireCert::NEVER; + else if (tls_require_cert_lc_str == "allow") + params.tls_require_cert = LDAPServerParams::TLSRequireCert::ALLOW; + else if (tls_require_cert_lc_str == "try") + params.tls_require_cert = LDAPServerParams::TLSRequireCert::TRY; + else if (tls_require_cert_lc_str == "demand") + params.tls_require_cert = LDAPServerParams::TLSRequireCert::DEMAND; + else + throw Exception("Bad value for 'tls_require_cert' entry, allowed values are: 'never', 'allow', 'try', 'demand'", ErrorCodes::BAD_ARGUMENTS); + } + + if (has_tls_cert_file) + params.tls_cert_file = config.getString(ldap_server_config + ".tls_cert_file"); + + if (has_tls_key_file) + params.tls_key_file = config.getString(ldap_server_config + ".tls_key_file"); + + if (has_tls_ca_cert_file) + params.tls_ca_cert_file = config.getString(ldap_server_config + ".tls_ca_cert_file"); + + if (has_tls_ca_cert_dir) + params.tls_ca_cert_dir = config.getString(ldap_server_config + ".tls_ca_cert_dir"); + + if (has_tls_cipher_suite) + params.tls_cipher_suite = config.getString(ldap_server_config + ".tls_cipher_suite"); if (has_port) { diff --git a/src/Access/LDAPClient.cpp b/src/Access/LDAPClient.cpp index b538c06c9ea..02c24bc9a9e 100644 --- a/src/Access/LDAPClient.cpp +++ b/src/Access/LDAPClient.cpp @@ -140,19 +140,23 @@ int LDAPClient::openConnection(const bool graceful_bind_failure) diag(ldap_set_option(handle, LDAP_OPT_KEEPCONN, LDAP_OPT_ON)); #endif +#ifdef LDAP_OPT_TIMEOUT { ::timeval operation_timeout; operation_timeout.tv_sec = params.operation_timeout.count(); operation_timeout.tv_usec = 0; diag(ldap_set_option(handle, LDAP_OPT_TIMEOUT, &operation_timeout)); } +#endif +#ifdef LDAP_OPT_NETWORK_TIMEOUT { ::timeval network_timeout; network_timeout.tv_sec = params.network_timeout.count(); network_timeout.tv_usec = 0; diag(ldap_set_option(handle, LDAP_OPT_NETWORK_TIMEOUT, &network_timeout)); } +#endif { const int search_timeout = params.search_timeout.count(); @@ -164,23 +168,59 @@ int LDAPClient::openConnection(const bool graceful_bind_failure) diag(ldap_set_option(handle, LDAP_OPT_SIZELIMIT, &size_limit)); } +#ifdef LDAP_OPT_X_TLS_PROTOCOL_MIN { int value = 0; - switch (params.tls_cert_verify) + switch (params.tls_minimum_protocol_version) { - case LDAPServerParams::TLSCertVerify::NEVER: value = LDAP_OPT_X_TLS_NEVER; break; - case LDAPServerParams::TLSCertVerify::ALLOW: value = LDAP_OPT_X_TLS_ALLOW; break; - case LDAPServerParams::TLSCertVerify::TRY: value = LDAP_OPT_X_TLS_TRY; break; - case LDAPServerParams::TLSCertVerify::DEMAND: value = LDAP_OPT_X_TLS_DEMAND; break; + case LDAPServerParams::TLSProtocolVersion::SSL2: value = LDAP_OPT_X_TLS_PROTOCOL_SSL2; break; + case LDAPServerParams::TLSProtocolVersion::SSL3: value = LDAP_OPT_X_TLS_PROTOCOL_SSL3; break; + case LDAPServerParams::TLSProtocolVersion::TLS1_0: value = LDAP_OPT_X_TLS_PROTOCOL_TLS1_0; break; + case LDAPServerParams::TLSProtocolVersion::TLS1_1: value = LDAP_OPT_X_TLS_PROTOCOL_TLS1_1; break; + case LDAPServerParams::TLSProtocolVersion::TLS1_2: value = LDAP_OPT_X_TLS_PROTOCOL_TLS1_2; break; + } + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_PROTOCOL_MIN, &value)); + } +#endif + +#ifdef LDAP_OPT_X_TLS_REQUIRE_CERT + { + int value = 0; + switch (params.tls_require_cert) + { + case LDAPServerParams::TLSRequireCert::NEVER: value = LDAP_OPT_X_TLS_NEVER; break; + case LDAPServerParams::TLSRequireCert::ALLOW: value = LDAP_OPT_X_TLS_ALLOW; break; + case LDAPServerParams::TLSRequireCert::TRY: value = LDAP_OPT_X_TLS_TRY; break; + case LDAPServerParams::TLSRequireCert::DEMAND: value = LDAP_OPT_X_TLS_DEMAND; break; } diag(ldap_set_option(handle, LDAP_OPT_X_TLS_REQUIRE_CERT, &value)); } +#endif - if (!params.ca_cert_dir.empty()) - diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTDIR, params.ca_cert_dir.c_str())); +#ifdef LDAP_OPT_X_TLS_CERTFILE + if (!params.tls_cert_file.empty()) + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CERTFILE, params.tls_cert_file.c_str())); +#endif - if (!params.ca_cert_file.empty()) - diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTFILE, params.ca_cert_file.c_str())); +#ifdef LDAP_OPT_X_TLS_KEYFILE + if (!params.tls_key_file.empty()) + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_KEYFILE, params.tls_key_file.c_str())); +#endif + +#ifdef LDAP_OPT_X_TLS_CACERTFILE + if (!params.tls_ca_cert_file.empty()) + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTFILE, params.tls_ca_cert_file.c_str())); +#endif + +#ifdef LDAP_OPT_X_TLS_CACERTDIR + if (!params.tls_ca_cert_dir.empty()) + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CACERTDIR, params.tls_ca_cert_dir.c_str())); +#endif + +#ifdef LDAP_OPT_X_TLS_CIPHER_SUITE + if (!params.tls_cipher_suite.empty()) + diag(ldap_set_option(handle, LDAP_OPT_X_TLS_CIPHER_SUITE, params.tls_cipher_suite.c_str())); +#endif #ifdef LDAP_OPT_X_TLS_NEWCTX { diff --git a/src/Access/LDAPParams.h b/src/Access/LDAPParams.h index ed28526d29d..0d7c7dd17cd 100644 --- a/src/Access/LDAPParams.h +++ b/src/Access/LDAPParams.h @@ -23,7 +23,16 @@ struct LDAPServerParams YES }; - enum class TLSCertVerify + enum class TLSProtocolVersion + { + SSL2, + SSL3, + TLS1_0, + TLS1_1, + TLS1_2 + }; + + enum class TLSRequireCert { NEVER, ALLOW, @@ -42,9 +51,13 @@ struct LDAPServerParams std::uint16_t port = 636; TLSEnable enable_tls = TLSEnable::YES; - TLSCertVerify tls_cert_verify = TLSCertVerify::DEMAND; - String ca_cert_dir; - String ca_cert_file; + TLSProtocolVersion tls_minimum_protocol_version = TLSProtocolVersion::TLS1_2; + TLSRequireCert tls_require_cert = TLSRequireCert::DEMAND; + String tls_cert_file; + String tls_key_file; + String tls_ca_cert_file; + String tls_ca_cert_dir; + String tls_cipher_suite; SASLMechanism sasl_mechanism = SASLMechanism::SIMPLE; From 6338225c501803b60bc7f888cda14dcc54a248f8 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Tue, 16 Jun 2020 17:49:18 +0400 Subject: [PATCH 027/143] Fix tls_cipher_suite example --- programs/server/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/server/config.xml b/programs/server/config.xml index f43ecad9a78..c4f508c6f33 100644 --- a/programs/server/config.xml +++ b/programs/server/config.xml @@ -231,7 +231,7 @@ /path/to/tls_key_file /path/to/tls_ca_cert_file /path/to/tls_ca_cert_dir - SECURE256:+SECURE128:-VERS-TLS-ALL:+VERS-TLS1.2:-RSA:-DHE-DSS:-CAMELLIA-128-CBC:-CAMELLIA-256-CBC + ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:AES256-GCM-SHA384 --> From 7317acb60949c752202d0a247a2568888ddd4cc4 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Thu, 18 Jun 2020 23:33:59 +0400 Subject: [PATCH 028/143] Silently reject empty passwords. Empty user names are rejected verbosely. --- src/Access/LDAPClient.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Access/LDAPClient.cpp b/src/Access/LDAPClient.cpp index 02c24bc9a9e..a85e96ab86c 100644 --- a/src/Access/LDAPClient.cpp +++ b/src/Access/LDAPClient.cpp @@ -267,16 +267,19 @@ void LDAPClient::closeConnection() noexcept bool LDAPSimpleAuthClient::check() { - bool result = false; - if (params.user.empty()) throw Exception("LDAP authentication of a user with an empty name is not allowed", ErrorCodes::BAD_ARGUMENTS); + if (params.password.empty()) + return false; // Silently reject authentication attempt if the password is empty as if it didn't match. + SCOPE_EXIT({ closeConnection(); }); const bool graceful_bind_failure = true; const auto rc = openConnection(graceful_bind_failure); + bool result = false; + switch (rc) { case LDAP_SUCCESS: From 93367e9b85b4e7f523912e5fb8e0b935a983b90f Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 19 Jun 2020 00:18:55 +0400 Subject: [PATCH 029/143] Rollback merge artefacts --- tests/integration/test_role/test.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/integration/test_role/test.py b/tests/integration/test_role/test.py index 6d6bc9452e3..e668b461389 100644 --- a/tests/integration/test_role/test.py +++ b/tests/integration/test_role/test.py @@ -11,7 +11,7 @@ instance = cluster.add_instance('instance') def started_cluster(): try: cluster.start() - + instance.query("CREATE TABLE test_table(x UInt32, y UInt32) ENGINE = MergeTree ORDER BY tuple()") instance.query("INSERT INTO test_table VALUES (1,5), (2,10)") @@ -35,7 +35,7 @@ def test_create_role(): instance.query('CREATE ROLE R1') assert "Not enough privileges" in instance.query_and_get_error("SELECT * FROM test_table", user='A') - + instance.query('GRANT SELECT ON test_table TO R1') assert "Not enough privileges" in instance.query_and_get_error("SELECT * FROM test_table", user='A') @@ -52,13 +52,13 @@ def test_grant_role_to_role(): instance.query('CREATE ROLE R2') assert "Not enough privileges" in instance.query_and_get_error("SELECT * FROM test_table", user='A') - + instance.query('GRANT R1 TO A') assert "Not enough privileges" in instance.query_and_get_error("SELECT * FROM test_table", user='A') - + instance.query('GRANT R2 TO R1') assert "Not enough privileges" in instance.query_and_get_error("SELECT * FROM test_table", user='A') - + instance.query('GRANT SELECT ON test_table TO R2') assert instance.query("SELECT * FROM test_table", user='A') == "1\t5\n2\t10\n" @@ -69,12 +69,12 @@ def test_combine_privileges(): instance.query('CREATE ROLE R2') assert "Not enough privileges" in instance.query_and_get_error("SELECT * FROM test_table", user='A') - + instance.query('GRANT R1 TO A') instance.query('GRANT SELECT(x) ON test_table TO R1') assert "Not enough privileges" in instance.query_and_get_error("SELECT * FROM test_table", user='A') assert instance.query("SELECT x FROM test_table", user='A') == "1\n2\n" - + instance.query('GRANT SELECT(y) ON test_table TO R2') instance.query('GRANT R2 TO A') assert instance.query("SELECT * FROM test_table", user='A') == "1\t5\n2\t10\n" From d17d72b075a00f34bc1753ff074c9f67616adc3c Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Tue, 23 Jun 2020 18:23:34 +0400 Subject: [PATCH 030/143] More generic DN in the example --- programs/server/config.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/programs/server/config.xml b/programs/server/config.xml index d73c72a6b20..454e611dc4a 100644 --- a/programs/server/config.xml +++ b/programs/server/config.xml @@ -222,8 +222,8 @@ localhost 636 - cn= - , ou=users, dc=example, dc=com + uid= + ,ou=users,dc=example,dc=com yes tls1.2 demand From e88719df211111ccbf255d8987f25d118118864c Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Wed, 24 Jun 2020 19:52:00 +0400 Subject: [PATCH 031/143] Fix the 01292_create_user test: auth_params column stores a JSON object instead of an array. --- tests/queries/0_stateless/01292_create_user.reference | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/queries/0_stateless/01292_create_user.reference b/tests/queries/0_stateless/01292_create_user.reference index 555bd99bd94..922ee54bef4 100644 --- a/tests/queries/0_stateless/01292_create_user.reference +++ b/tests/queries/0_stateless/01292_create_user.reference @@ -95,10 +95,10 @@ CREATE USER u2_01292 DEFAULT ROLE r1_01292, r2_01292 SETTINGS readonly = 1 CREATE USER u3_01292 HOST LIKE \'%.%.myhost.com\' DEFAULT ROLE r1_01292, r2_01292 CREATE USER u4_01292 HOST LIKE \'%.%.myhost.com\' DEFAULT ROLE r1_01292, r2_01292 -- system.users -u1_01292 disk plaintext_password [] [] ['localhost'] [] [] 1 [] [] -u2_01292 disk no_password [] [] [] [] ['%.%.myhost.com'] 0 [] [] -u3_01292 disk sha256_password [] ['192.169.1.1','192.168.0.0/16'] ['localhost'] [] [] 0 ['r1_01292'] [] -u4_01292 disk double_sha1_password [] ['::/0'] [] [] [] 1 [] ['r1_01292'] +u1_01292 disk plaintext_password {} [] ['localhost'] [] [] 1 [] [] +u2_01292 disk no_password {} [] [] [] ['%.%.myhost.com'] 0 [] [] +u3_01292 disk sha256_password {} ['192.169.1.1','192.168.0.0/16'] ['localhost'] [] [] 0 ['r1_01292'] [] +u4_01292 disk double_sha1_password {} ['::/0'] [] [] [] 1 [] ['r1_01292'] -- system.settings_profile_elements \N u1_01292 \N 0 readonly 1 \N \N \N \N \N u2_01292 \N 0 \N \N \N \N \N default From 608ecbc290b711c45b32e5ab523a766230a29651 Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Mon, 29 Jun 2020 14:55:27 +0200 Subject: [PATCH 032/143] Adding LDAP functional tests. --- tests/functional/helpers/argparser.py | 13 + tests/functional/helpers/cluster.py | 272 +++++ tests/functional/ldap/__init__.py | 0 tests/functional/ldap/configs/CA/ca.crt | 22 + tests/functional/ldap/configs/CA/ca.key | 30 + tests/functional/ldap/configs/CA/ca.srl | 1 + tests/functional/ldap/configs/CA/dhparam.pem | 5 + .../functional/ldap/configs/CA/passphrase.txt | 1 + .../ldap/configs/clickhouse/common.xml | 6 + .../ldap/configs/clickhouse/config.d/logs.xml | 17 + .../configs/clickhouse/config.d/ports.xml | 5 + .../configs/clickhouse/config.d/remote.xml | 107 ++ .../ldap/configs/clickhouse/config.d/ssl.xml | 17 + .../configs/clickhouse/config.d/storage.xml | 20 + .../configs/clickhouse/config.d/zookeeper.xml | 10 + .../ldap/configs/clickhouse/config.xml | 436 ++++++++ .../ldap/configs/clickhouse/ssl/dhparam.pem | 8 + .../ldap/configs/clickhouse/ssl/server.crt | 19 + .../ldap/configs/clickhouse/ssl/server.key | 28 + .../ldap/configs/clickhouse/users.xml | 133 +++ .../configs/clickhouse1/config.d/macros.xml | 8 + .../configs/clickhouse2/config.d/macros.xml | 8 + .../configs/clickhouse3/config.d/macros.xml | 8 + .../ldap/configs/ldap1/config/export.ldif | 64 ++ .../ldap/configs/ldap2/certs/ca.crt | 22 + .../ldap/configs/ldap2/certs/dhparam.pem | 5 + .../ldap/configs/ldap2/certs/ldap.crt | 20 + .../ldap/configs/ldap2/certs/ldap.csr | 17 + .../ldap/configs/ldap2/certs/ldap.key | 27 + .../ldap/configs/ldap2/config/export.ldif | 64 ++ .../ldap/configs/ldap3/certs/ca.crt | 22 + .../ldap/configs/ldap3/certs/dhparam.pem | 5 + .../ldap/configs/ldap3/certs/ldap.crt | 20 + .../ldap/configs/ldap3/certs/ldap.csr | 17 + .../ldap/configs/ldap3/certs/ldap.key | 27 + .../ldap/configs/ldap3/config/export.ldif | 64 ++ .../ldap/configs/ldap4/config/export.ldif | 64 ++ .../ldap/configs/ldap5/config/export.ldif | 64 ++ .../ldap/configs/ldap5/ldap2/certs/ca.crt | 22 + .../configs/ldap5/ldap2/certs/dhparam.pem | 5 + .../ldap/configs/ldap5/ldap2/certs/ldap.crt | 20 + .../ldap/configs/ldap5/ldap2/certs/ldap.csr | 17 + .../ldap/configs/ldap5/ldap2/certs/ldap.key | 27 + .../configs/ldap5/ldap2/config/export.ldif | 64 ++ .../docker-compose/clickhouse-service.yml | 28 + .../ldap/docker-compose/docker-compose.yml | 162 +++ .../ldap/docker-compose/openldap-service.yml | 40 + .../ldap/docker-compose/zookeeper-service.yml | 18 + tests/functional/ldap/regression.py | 54 + .../functional/ldap/requirements/__init__.py | 1 + .../ldap/requirements/requirements.py | 928 ++++++++++++++++++ .../functional/ldap/tests/authentications.py | 460 +++++++++ tests/functional/ldap/tests/common.py | 354 +++++++ tests/functional/ldap/tests/connections.py | 285 ++++++ .../functional/ldap/tests/multiple_servers.py | 38 + tests/functional/ldap/tests/sanity.py | 42 + tests/functional/ldap/tests/server_config.py | 263 +++++ tests/functional/ldap/tests/user_config.py | 162 +++ tests/functional/regression.py | 19 + 59 files changed, 4685 insertions(+) create mode 100644 tests/functional/helpers/argparser.py create mode 100644 tests/functional/helpers/cluster.py create mode 100644 tests/functional/ldap/__init__.py create mode 100644 tests/functional/ldap/configs/CA/ca.crt create mode 100644 tests/functional/ldap/configs/CA/ca.key create mode 100644 tests/functional/ldap/configs/CA/ca.srl create mode 100644 tests/functional/ldap/configs/CA/dhparam.pem create mode 100644 tests/functional/ldap/configs/CA/passphrase.txt create mode 100644 tests/functional/ldap/configs/clickhouse/common.xml create mode 100644 tests/functional/ldap/configs/clickhouse/config.d/logs.xml create mode 100644 tests/functional/ldap/configs/clickhouse/config.d/ports.xml create mode 100644 tests/functional/ldap/configs/clickhouse/config.d/remote.xml create mode 100644 tests/functional/ldap/configs/clickhouse/config.d/ssl.xml create mode 100644 tests/functional/ldap/configs/clickhouse/config.d/storage.xml create mode 100644 tests/functional/ldap/configs/clickhouse/config.d/zookeeper.xml create mode 100644 tests/functional/ldap/configs/clickhouse/config.xml create mode 100644 tests/functional/ldap/configs/clickhouse/ssl/dhparam.pem create mode 100644 tests/functional/ldap/configs/clickhouse/ssl/server.crt create mode 100644 tests/functional/ldap/configs/clickhouse/ssl/server.key create mode 100644 tests/functional/ldap/configs/clickhouse/users.xml create mode 100644 tests/functional/ldap/configs/clickhouse1/config.d/macros.xml create mode 100644 tests/functional/ldap/configs/clickhouse2/config.d/macros.xml create mode 100644 tests/functional/ldap/configs/clickhouse3/config.d/macros.xml create mode 100644 tests/functional/ldap/configs/ldap1/config/export.ldif create mode 100644 tests/functional/ldap/configs/ldap2/certs/ca.crt create mode 100644 tests/functional/ldap/configs/ldap2/certs/dhparam.pem create mode 100644 tests/functional/ldap/configs/ldap2/certs/ldap.crt create mode 100644 tests/functional/ldap/configs/ldap2/certs/ldap.csr create mode 100644 tests/functional/ldap/configs/ldap2/certs/ldap.key create mode 100644 tests/functional/ldap/configs/ldap2/config/export.ldif create mode 100644 tests/functional/ldap/configs/ldap3/certs/ca.crt create mode 100644 tests/functional/ldap/configs/ldap3/certs/dhparam.pem create mode 100644 tests/functional/ldap/configs/ldap3/certs/ldap.crt create mode 100644 tests/functional/ldap/configs/ldap3/certs/ldap.csr create mode 100644 tests/functional/ldap/configs/ldap3/certs/ldap.key create mode 100644 tests/functional/ldap/configs/ldap3/config/export.ldif create mode 100644 tests/functional/ldap/configs/ldap4/config/export.ldif create mode 100644 tests/functional/ldap/configs/ldap5/config/export.ldif create mode 100644 tests/functional/ldap/configs/ldap5/ldap2/certs/ca.crt create mode 100644 tests/functional/ldap/configs/ldap5/ldap2/certs/dhparam.pem create mode 100644 tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.crt create mode 100644 tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.csr create mode 100644 tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.key create mode 100644 tests/functional/ldap/configs/ldap5/ldap2/config/export.ldif create mode 100644 tests/functional/ldap/docker-compose/clickhouse-service.yml create mode 100644 tests/functional/ldap/docker-compose/docker-compose.yml create mode 100644 tests/functional/ldap/docker-compose/openldap-service.yml create mode 100644 tests/functional/ldap/docker-compose/zookeeper-service.yml create mode 100755 tests/functional/ldap/regression.py create mode 100644 tests/functional/ldap/requirements/__init__.py create mode 100644 tests/functional/ldap/requirements/requirements.py create mode 100644 tests/functional/ldap/tests/authentications.py create mode 100644 tests/functional/ldap/tests/common.py create mode 100644 tests/functional/ldap/tests/connections.py create mode 100644 tests/functional/ldap/tests/multiple_servers.py create mode 100644 tests/functional/ldap/tests/sanity.py create mode 100644 tests/functional/ldap/tests/server_config.py create mode 100644 tests/functional/ldap/tests/user_config.py create mode 100755 tests/functional/regression.py diff --git a/tests/functional/helpers/argparser.py b/tests/functional/helpers/argparser.py new file mode 100644 index 00000000000..34b91453876 --- /dev/null +++ b/tests/functional/helpers/argparser.py @@ -0,0 +1,13 @@ +import os + +def argparser(parser): + """Default argument parser for regressions. + """ + parser.add_argument("--local", + action="store_true", + help="run regression in local mode", default=False) + + parser.add_argument("--clickhouse-binary-path", + type=str, dest="clickhouse_binary_path", + help="path to ClickHouse binary, default: /usr/bin/clickhouse", metavar="path", + default=os.getenv("CLICKHOUSE_TESTS_SERVER_BIN_PATH", "/usr/bin/clickhouse")) diff --git a/tests/functional/helpers/cluster.py b/tests/functional/helpers/cluster.py new file mode 100644 index 00000000000..e087b3b5b9d --- /dev/null +++ b/tests/functional/helpers/cluster.py @@ -0,0 +1,272 @@ +import os +import time +import inspect +import threading +import tempfile + +from testflows.core import * +from testflows.asserts import error +from testflows.connect import Shell + +class QueryRuntimeException(Exception): + """Exception during query execution on the server. + """ + pass + +class Node(object): + """Generic cluster node. + """ + config_d_dir = "/etc/clickhouse-server/config.d/" + + def __init__(self, cluster, name): + self.cluster = cluster + self.name = name + + def repr(self): + return f"Node(name='{self.name}')" + + def restart(self, timeout=120, safe=True): + """Restart node. + """ + with self.cluster.lock: + for key in list(self.cluster._bash.keys()): + if key.endswith(f"-{self.name}"): + shell = self.cluster._bash.pop(key) + shell.__exit__(None, None, None) + + self.cluster.command(None, f'{self.cluster.docker_compose} restart {self.name}', timeout=timeout) + + def command(self, *args, **kwargs): + return self.cluster.command(self.name, *args, **kwargs) + +class ClickHouseNode(Node): + """Node with ClickHouse server. + """ + def wait_healthy(self, timeout=120): + with By(f"waiting until container {self.name} is healthy"): + start_time = time.time() + while True: + if self.query("select 1", no_checks=1, timeout=120, steps=False).exitcode == 0: + break + if time.time() - start_time < timeout: + time.sleep(2) + continue + assert False, "container is not healthy" + + def restart(self, timeout=120, safe=True): + """Restart node. + """ + if safe: + self.query("SYSTEM STOP MOVES") + self.query("SYSTEM STOP MERGES") + self.query("SYSTEM FLUSH LOGS") + with By("waiting for 5 sec for moves and merges to stop"): + time.sleep(5) + with And("forcing to sync everything to disk"): + self.command("sync", timeout=30) + + with self.cluster.lock: + for key in list(self.cluster._bash.keys()): + if key.endswith(f"-{self.name}"): + shell = self.cluster._bash.pop(key) + shell.__exit__(None, None, None) + + self.cluster.command(None, f'{self.cluster.docker_compose} restart {self.name}', timeout=timeout) + + self.wait_healthy(timeout) + + def query(self, sql, message=None, exitcode=None, steps=True, no_checks=False, + raise_on_exception=False, step=By, settings=None, *args, **kwargs): + """Execute and check query. + + :param sql: sql query + :param message: expected message that should be in the output, default: None + :param exitcode: expected exitcode, default: None + """ + if len(sql) > 1024: + with tempfile.NamedTemporaryFile("w", encoding="utf-8") as query: + query.write(sql) + query.flush() + command = f"cat \"{query.name}\" | {self.cluster.docker_compose} exec -T {self.name} clickhouse client -n" + for setting in settings or []: + name, value = setting + command += f" --{name} \"{value}\"" + description = f""" + echo -e \"{sql[:100]}...\" > {query.name} + {command} + """ + with step("executing command", description=description) if steps else NullStep(): + r = self.cluster.bash(None)(command, *args, **kwargs) + else: + command = f"echo -e \"{sql}\" | clickhouse client -n" + for setting in settings or []: + name, value = setting + command += f" --{name} \"{value}\"" + with step("executing command", description=command) if steps else NullStep(): + r = self.cluster.bash(self.name)(command, *args, **kwargs) + + if no_checks: + return r + + if exitcode is not None: + with Then(f"exitcode should be {exitcode}") if steps else NullStep(): + assert r.exitcode == exitcode, error(r.output) + + if message is not None: + with Then(f"output should contain message", description=message) if steps else NullStep(): + assert message in r.output, error(r.output) + + if message is None or "Exception:" not in message: + with Then("check if output has exception") if steps else NullStep(): + if "Exception:" in r.output: + if raise_on_exception: + raise QueryRuntimeException(r.output) + assert False, error(r.output) + + return r + +class Cluster(object): + """Simple object around docker-compose cluster. + """ + def __init__(self, local=False, + clickhouse_binary_path=None, configs_dir=None, + nodes=None, + docker_compose="docker-compose", docker_compose_project_dir=None, + docker_compose_file="docker-compose.yml"): + + self._bash = {} + self.clickhouse_binary_path = clickhouse_binary_path + self.configs_dir = configs_dir + self.local = local + self.nodes = nodes or {} + self.docker_compose = docker_compose + + frame = inspect.currentframe().f_back + caller_dir = os.path.dirname(os.path.abspath(frame.f_globals["__file__"])) + + # auto set configs directory + if self.configs_dir is None: + caller_configs_dir = caller_dir + if os.path.exists(caller_configs_dir): + self.configs_dir = caller_configs_dir + + if not os.path.exists(self.configs_dir): + raise TypeError("configs directory '{self.configs_dir}' does not exist") + + # auto set docker-compose project directory + if docker_compose_project_dir is None: + caller_project_dir = os.path.join(caller_dir, "docker-compose") + if os.path.exists(caller_project_dir): + docker_compose_project_dir = caller_project_dir + + docker_compose_file_path = os.path.join(docker_compose_project_dir or "", docker_compose_file) + + if not os.path.exists(docker_compose_file_path): + raise TypeError("docker compose file '{docker_compose_file_path}' does not exist") + + self.docker_compose += f" --project-directory \"{docker_compose_project_dir}\" --file \"{docker_compose_file_path}\"" + self.lock = threading.Lock() + + def bash(self, node, timeout=60): + """Returns thread-local bash terminal + to a specific node. + + :param node: name of the service + """ + current_thread = threading.current_thread() + id = f"{current_thread.ident}-{node}" + with self.lock: + if self._bash.get(id) is None: + if node is None: + self._bash[id] = Shell().__enter__() + else: + self._bash[id] = Shell(command=[ + "/bin/bash", "--noediting", "-c", f"{self.docker_compose} exec {node} bash --noediting" + ], name=node).__enter__() + self._bash[id].timeout = timeout + return self._bash[id] + + def __enter__(self): + with Given("docker-compose cluster"): + self.up() + return self + + def __exit__(self, type, value, traceback): + try: + with Finally("I clean up"): + self.down() + finally: + with self.lock: + for shell in self._bash.values(): + shell.__exit__(type, value, traceback) + + def node(self, name): + """Get object with node bound methods. + + :param name: name of service name + """ + if name.startswith("clickhouse"): + return ClickHouseNode(self, name) + return Node(self, name) + + def down(self, timeout=120): + """Bring cluster down by executing docker-compose down.""" + try: + bash = self.bash(None) + with self.lock: + # remove and close all not None node terminals + for id in list(self._bash.keys()): + shell = self._bash.pop(id) + if shell is not bash: + shell.__exit__(None, None, None) + else: + self._bash[id] = shell + finally: + return self.command(None, f"{self.docker_compose} down", timeout=timeout) + + def up(self): + if self.local: + with Given("I am running in local mode"): + with Then("check --clickhouse-binary-path is specified"): + assert self.clickhouse_binary_path, "when running in local mode then --clickhouse-binary-path must be specified" + with And("path should exist"): + assert os.path.exists(self.clickhouse_binary_path) + + os.environ["CLICKHOUSE_TESTS_SERVER_BIN_PATH"] = self.clickhouse_binary_path + os.environ["CLICKHOUSE_TESTS_ODBC_BRIDGE_BIN_PATH"] = os.path.join(os.path.dirname(self.clickhouse_binary_path), + "clickhouse-odbc-bridge") + os.environ["CLICKHOUSE_TESTS_DIR"] = self.configs_dir + + with Given("docker-compose"): + self.command(None, "env | grep CLICKHOUSE") + cmd = self.command(None, f'{self.docker_compose} up -d 2>&1 | tee', timeout=30 * 60) + else: + with Given("docker-compose"): + cmd = self.command(None, f'{self.docker_compose} up -d --no-recreate 2>&1 | tee') + + with Then("check there are no unhealthy containers"): + assert "is unhealthy" not in cmd.output, error() + + with Then("wait all nodes report healhy"): + for name in self.nodes["clickhouse"]: + self.node(name).wait_healthy() + + def command(self, node, command, message=None, exitcode=None, steps=True, *args, **kwargs): + """Execute and check command. + + :param node: name of the service + :param command: command + :param message: expected message that should be in the output, default: None + :param exitcode: expected exitcode, default: None + :param steps: don't break command into steps, default: True + """ + debug(f"command() {node}, {command}") + with By("executing command", description=command) if steps else NullStep(): + r = self.bash(node)(command, *args, **kwargs) + if exitcode is not None: + with Then(f"exitcode should be {exitcode}") if steps else NullStep(): + assert r.exitcode == exitcode, error(r.output) + if message is not None: + with Then(f"output should contain message", description=message) if steps else NullStep(): + assert message in r.output, error(r.output) + return r diff --git a/tests/functional/ldap/__init__.py b/tests/functional/ldap/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/functional/ldap/configs/CA/ca.crt b/tests/functional/ldap/configs/CA/ca.crt new file mode 100644 index 00000000000..8c71e3afc91 --- /dev/null +++ b/tests/functional/ldap/configs/CA/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDlTCCAn2gAwIBAgIUJBqw2dHM2DDCZjYSkPOESlvDH6swDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgMAk9OMQ8wDQYDVQQHDAZPdHRhd2Ex +ETAPBgNVBAoMCEFsdGluaXR5MQswCQYDVQQLDAJRQTENMAsGA1UEAwwEcm9vdDAe +Fw0yMDA2MTExOTAzNDhaFw0zMDA2MDkxOTAzNDhaMFoxCzAJBgNVBAYTAkNBMQsw +CQYDVQQIDAJPTjEPMA0GA1UEBwwGT3R0YXdhMREwDwYDVQQKDAhBbHRpbml0eTEL +MAkGA1UECwwCUUExDTALBgNVBAMMBHJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQC9Irr0zGV+HCI2fZ0ht4hR5It4Sbjz4RwZV8ENRP/+TEz8l9eK +J6ygxhKX7SMYzIs/jS9Gsq4plX1r2ujW1qRf8yLpR4+dGLP+jBRi1drj0XjZXosT +SERjWzgPauWxL9LN8+l26eBAqz6fw5e0W8WRSTgf5iGiCcKOTmaATIUjP0CdfWKK +qpktI4vhe++CXZFJ3usR+8KZ/FwwbCLJM/3J2HnbcXfcaYPYvr1tfqLudKSTbG9H +M3+AVwjctdesc/0sbd51Zsm0ClQptMbuKnDCYauGg61kNkgbgPgRmH9Pzo67DtxF +/WW+PtOzq8xLOifciQ9Piboy9QBSQZGwf4wzAgMBAAGjUzBRMB0GA1UdDgQWBBSi +njya0RDozx3OZTLYFpwqYnlpIDAfBgNVHSMEGDAWgBSinjya0RDozx3OZTLYFpwq +YnlpIDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBAD7VyFg7F +U1C25KFvtauchAOjCW6w7U/b3z1dVZvcQ88/kH1VsLUcfGixlSilUEfPTJsi7OA0 +R5BQdh2GGcjUJv4iqEFGU05KvMVmRRKn08P62+ZhJxKMxG26VzcliRZzCMkI6d0W +lFwI6nM45yeqdHVh5k4xbuJzqpbD9BtXXLI+/Ra9Fx8S9ETA3GdidpZLU5P1VLxq +UuedfqyAVWZXpr6TAURGxouRmRzul9yFzbSUex+MLEIPrstjtEwV3+tBQZJz9xAS +TVPj+Nv3LO7GCq54bdwkq1ioWbSL2hEmABkj6kdW/JwmfhGHf/2rirDVMzrTYw07 +dFJfAZC+FEsv +-----END CERTIFICATE----- diff --git a/tests/functional/ldap/configs/CA/ca.key b/tests/functional/ldap/configs/CA/ca.key new file mode 100644 index 00000000000..e7a7f664dcf --- /dev/null +++ b/tests/functional/ldap/configs/CA/ca.key @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: AES-256-CBC,D06B9754A2069EBB4E77065DC9B605A1 + +FJT794Z6AUuUB5Vp5W2iR6zzCvQUg2dtKoE+xhFdbgC7lmSfA2W/O9fx15Il67Yj +Bbpm9Y6yteUSDQpJrvBdkhXeBkYEa5K1CA+0Jdx98nzwP3KBhHNxVVrTWRc5kniB +LMV3iBQEbAafxgL7gN+EWr3eV7w7ZSqT7D5br/mlBALU62gv2UzwTXLu1CgyNWMC +HIPjIX50Zga+BnhZhtQvM4Yj1gOsn+X6AaEZ3KjTfCDqthYQf2ldswW4gAlPAq83 ++INq9Spx+QG97Z+1XO2DmmGTZL0z+OFLT+3y26/UcftM26ODY09Dcf3gt0n6RIUV +0KsD1qQL0ppu4CHVnbIkOKMBe86qBl+kG8FVmyhgZ8D9ULlF1tpyTVKvHR82V2B5 +ztbc5EY1Fhb+r7OVVJlbCeo/bWmWybODZrpN49x5gGZpM3+8ApaHupGZ+cRFkQKG +rDpqC5gflT3WwFNxtP5noWcV+Gzb3riXNM3c8G5aIpLZwmmaTLK9ahKqMcq4Ljf+ +hir8kuCMqIKt3m7Ceoj4wAHSP8xO0y/cc1WYNb3CI0Emk795aR6IPUw4vDEXHG27 +OLoCJTvl/JKRWJGkdQx8wKAs/uw/qwtbhYoQJccTjfvy4NXH3tpSgxCE8OTWuEch +TAN8ra1PDGAUu+1MeT5gZ9uI1BEU6hXMME4mVRpJdcmw9MVy3V+B6rkUqX3kFAfR +e2ueF5qgIp+A4/UlVe5cKdWAQxu4BnUESLooA7cbgcLypdao9bRx9bXH8S3aNgxW +IdgICpc/v8wAX2yqMe191KgR9Vh1p0RCw/kEGVgWfY/IaQpsaYuq5quZbvr/fN5T +d++ySAMaPysaCadLUdZJLw56uk4Y+PYzR+ygjTX9dCCHedrAU8RYM55FJ/fyD3bQ +Hn9/n7PZyWy6u/TYt6dhlcYxaS3Opzw4eAQB8tGZJRYQ3AKpHpTEC57lXoMnUPKo ++nBmb0+YulylMZdns0WIBJlcv6qzIaNhDMrjyi18n1ezzPIGH7ivUjoXy2FL23q5 +f3aqJK4UUDEDkC8IeZkS+ykYxnohjFDhUyBe5gjryLqdMdy9EerehCWPf425AztX +c/EWPzDl46qmxWhugOlz3Fiw95VlYu0MUDRayHuZiYPplgJypChuU4EHJ+q8V2z3 +BwjSo1bD4nfc8f68qEOtdZ1u/ClcolMwlZQYDJz/DiE4JOcd2Gx4QSF5vaInm0/4 +mMj/ZWna4DAYFbH8IGh7xUPDqeIWhBYlgrD69ajKyay5Vu3La/d2QW20BhX35Ro2 +ZJVR+lfioMmxn4y481H2pv+5gOlGwh02Oa8qLhZBb8W+DvFShNk6mk87eCForFFT +CDgmvfsC/cS2wZkcFTecq6vbjFlt+OF13NCKlcO3wCm44D+bwVPeMrU6HycCVQw7 +SASrnP/th5sJbv11byb2lKgVdVHWk090bqnDwB9H2hGIb9JnPC9ZpaL/mocYyzTi +H9fcBrMYkL09FJGr3Uff7qEY4XQTMlLadXue3iKd19PRgV8cRyKp37MYI9/3iLwv +eYHLtMfrifZahf1ksOPeBphnlfzWo9qqfooUCaGxfSlNPUHhrHZ4aMiRyTE8Xeh2 +-----END RSA PRIVATE KEY----- diff --git a/tests/functional/ldap/configs/CA/ca.srl b/tests/functional/ldap/configs/CA/ca.srl new file mode 100644 index 00000000000..66feb9c8a35 --- /dev/null +++ b/tests/functional/ldap/configs/CA/ca.srl @@ -0,0 +1 @@ +227B125D27B6B1A4B5955361365DF8EC2D7098C1 diff --git a/tests/functional/ldap/configs/CA/dhparam.pem b/tests/functional/ldap/configs/CA/dhparam.pem new file mode 100644 index 00000000000..0a96faffd62 --- /dev/null +++ b/tests/functional/ldap/configs/CA/dhparam.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAJitt2hhnpDViQ5ko2ipBMdjy+bZ6FR/WdZ987R7lQvBkKehPXmxtEyV +AO6ofv5CZSDJokc5bUeBOAtg0EhMTCH82uPdwQvt58jRXcxXBg4JTjkx+oW9LBv2 +FdZsbaX8+SYivmiZ0Jp8T/HBm/4DA9VBS0O5GFRS4C7dHhmSTPfDAgEC +-----END DH PARAMETERS----- diff --git a/tests/functional/ldap/configs/CA/passphrase.txt b/tests/functional/ldap/configs/CA/passphrase.txt new file mode 100644 index 00000000000..2cf58b2364c --- /dev/null +++ b/tests/functional/ldap/configs/CA/passphrase.txt @@ -0,0 +1 @@ +altinity diff --git a/tests/functional/ldap/configs/clickhouse/common.xml b/tests/functional/ldap/configs/clickhouse/common.xml new file mode 100644 index 00000000000..df952b28c82 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/common.xml @@ -0,0 +1,6 @@ + + Europe/Moscow + 0.0.0.0 + /var/lib/clickhouse/ + /var/lib/clickhouse/tmp/ + diff --git a/tests/functional/ldap/configs/clickhouse/config.d/logs.xml b/tests/functional/ldap/configs/clickhouse/config.d/logs.xml new file mode 100644 index 00000000000..bdf1bbc11c1 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/config.d/logs.xml @@ -0,0 +1,17 @@ + + 3 + + trace + /var/log/clickhouse-server/log.log + /var/log/clickhouse-server/log.err.log + 1000M + 10 + /var/log/clickhouse-server/stderr.log + /var/log/clickhouse-server/stdout.log + + + system + part_log
+ 500 +
+
diff --git a/tests/functional/ldap/configs/clickhouse/config.d/ports.xml b/tests/functional/ldap/configs/clickhouse/config.d/ports.xml new file mode 100644 index 00000000000..fbc6cea74c0 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/config.d/ports.xml @@ -0,0 +1,5 @@ + + + 8443 + 9440 + \ No newline at end of file diff --git a/tests/functional/ldap/configs/clickhouse/config.d/remote.xml b/tests/functional/ldap/configs/clickhouse/config.d/remote.xml new file mode 100644 index 00000000000..51be2a6e8e3 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/config.d/remote.xml @@ -0,0 +1,107 @@ + + + + + + true + + clickhouse1 + 9000 + + + clickhouse2 + 9000 + + + clickhouse3 + 9000 + + + + + + + true + + clickhouse1 + 9440 + 1 + + + clickhouse2 + 9440 + 1 + + + clickhouse3 + 9440 + 1 + + + + + + + clickhouse1 + 9000 + + + + + clickhouse2 + 9000 + + + + + clickhouse3 + 9000 + + + + + + + clickhouse1 + 9440 + 1 + + + + + clickhouse2 + 9440 + 1 + + + + + clickhouse3 + 9440 + 1 + + + + + diff --git a/tests/functional/ldap/configs/clickhouse/config.d/ssl.xml b/tests/functional/ldap/configs/clickhouse/config.d/ssl.xml new file mode 100644 index 00000000000..ca65ffd5e04 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/config.d/ssl.xml @@ -0,0 +1,17 @@ + + + + /etc/clickhouse-server/ssl/server.crt + /etc/clickhouse-server/ssl/server.key + none + true + + + true + none + + AcceptCertificateHandler + + + + diff --git a/tests/functional/ldap/configs/clickhouse/config.d/storage.xml b/tests/functional/ldap/configs/clickhouse/config.d/storage.xml new file mode 100644 index 00000000000..618fd6b6d24 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/config.d/storage.xml @@ -0,0 +1,20 @@ + + + + + + 1024 + + + + + + + default + + + + + + + diff --git a/tests/functional/ldap/configs/clickhouse/config.d/zookeeper.xml b/tests/functional/ldap/configs/clickhouse/config.d/zookeeper.xml new file mode 100644 index 00000000000..96270e7b645 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/config.d/zookeeper.xml @@ -0,0 +1,10 @@ + + + + + zookeeper + 2181 + + 15000 + + diff --git a/tests/functional/ldap/configs/clickhouse/config.xml b/tests/functional/ldap/configs/clickhouse/config.xml new file mode 100644 index 00000000000..d34d2c35253 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/config.xml @@ -0,0 +1,436 @@ + + + + + + trace + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + + 8123 + 9000 + + + + + + + + + /etc/clickhouse-server/server.crt + /etc/clickhouse-server/server.key + + /etc/clickhouse-server/dhparam.pem + none + true + true + sslv2,sslv3 + true + + + + true + true + sslv2,sslv3 + true + + + + RejectCertificateHandler + + + + + + + + + 9009 + + + + + + + + + + + + + + + + + + + + 4096 + 3 + + + 100 + + + + + + 8589934592 + + + 5368709120 + + + + /var/lib/clickhouse/ + + + /var/lib/clickhouse/tmp/ + + + /var/lib/clickhouse/user_files/ + + + /var/lib/clickhouse/access/ + + + users.xml + + + default + + + + + + default + + + + + + + + + false + + + + + + + + localhost + 9000 + + + + + + + localhost + 9000 + + + + + localhost + 9000 + + + + + + + localhost + 9440 + 1 + + + + + + + localhost + 9000 + + + + + localhost + 1 + + + + + + + + + + + + + + + + + 3600 + + + + 3600 + + + 60 + + + + + + + + + + system + query_log
+ + toYYYYMM(event_date) + + 7500 +
+ + + + system + trace_log
+ + toYYYYMM(event_date) + 7500 +
+ + + + system + query_thread_log
+ toYYYYMM(event_date) + 7500 +
+ + + + + + + + + + + + + + + + *_dictionary.xml + + + + + + + + + + /clickhouse/task_queue/ddl + + + + + + + + + + + + + + + + click_cost + any + + 0 + 3600 + + + 86400 + 60 + + + + max + + 0 + 60 + + + 3600 + 300 + + + 86400 + 3600 + + + + + + /var/lib/clickhouse/format_schemas/ + + + +
diff --git a/tests/functional/ldap/configs/clickhouse/ssl/dhparam.pem b/tests/functional/ldap/configs/clickhouse/ssl/dhparam.pem new file mode 100644 index 00000000000..2e6cee0798d --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/ssl/dhparam.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBCAKCAQEAua92DDli13gJ+//ZXyGaggjIuidqB0crXfhUlsrBk9BV1hH3i7fR +XGP9rUdk2ubnB3k2ejBStL5oBrkHm9SzUFSQHqfDjLZjKoUpOEmuDc4cHvX1XTR5 +Pr1vf5cd0yEncJWG5W4zyUB8k++SUdL2qaeslSs+f491HBLDYn/h8zCgRbBvxhxb +9qeho1xcbnWeqkN6Kc9bgGozA16P9NLuuLttNnOblkH+lMBf42BSne/TWt3AlGZf +slKmmZcySUhF8aKfJnLKbkBCFqOtFRh8zBA9a7g+BT/lSANATCDPaAk1YVih2EKb +dpc3briTDbRsiqg2JKMI7+VdULY9bh3EawIBAg== +-----END DH PARAMETERS----- diff --git a/tests/functional/ldap/configs/clickhouse/ssl/server.crt b/tests/functional/ldap/configs/clickhouse/ssl/server.crt new file mode 100644 index 00000000000..7ade2d96273 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/ssl/server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIC/TCCAeWgAwIBAgIJANjx1QSR77HBMA0GCSqGSIb3DQEBCwUAMBQxEjAQBgNV +BAMMCWxvY2FsaG9zdDAgFw0xODA3MzAxODE2MDhaGA8yMjkyMDUxNDE4MTYwOFow +FDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAs9uSo6lJG8o8pw0fbVGVu0tPOljSWcVSXH9uiJBwlZLQnhN4SFSFohfI +4K8U1tBDTnxPLUo/V1K9yzoLiRDGMkwVj6+4+hE2udS2ePTQv5oaMeJ9wrs+5c9T +4pOtlq3pLAdm04ZMB1nbrEysceVudHRkQbGHzHp6VG29Fw7Ga6YpqyHQihRmEkTU +7UCYNA+Vk7aDPdMS/khweyTpXYZimaK9f0ECU3/VOeG3fH6Sp2X6FN4tUj/aFXEj +sRmU5G2TlYiSIUMF2JPdhSihfk1hJVALrHPTU38SOL+GyyBRWdNcrIwVwbpvsvPg +pryMSNxnpr0AK0dFhjwnupIv5hJIOQIDAQABo1AwTjAdBgNVHQ4EFgQUjPLb3uYC +kcamyZHK4/EV8jAP0wQwHwYDVR0jBBgwFoAUjPLb3uYCkcamyZHK4/EV8jAP0wQw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAM/ocuDvfPus/KpMVD51j +4IdlU8R0vmnYLQ+ygzOAo7+hUWP5j0yvq4ILWNmQX6HNvUggCgFv9bjwDFhb/5Vr +85ieWfTd9+LTjrOzTw4avdGwpX9G+6jJJSSq15tw5ElOIFb/qNA9O4dBiu8vn03C +L/zRSXrARhSqTW5w/tZkUcSTT+M5h28+Lgn9ysx4Ff5vi44LJ1NnrbJbEAIYsAAD ++UA+4MBFKx1r6hHINULev8+lCfkpwIaeS8RL+op4fr6kQPxnULw8wT8gkuc8I4+L +P9gg/xDHB44T3ADGZ5Ib6O0DJaNiToO6rnoaaxs0KkotbvDWvRoxEytSbXKoYjYp +0g== +-----END CERTIFICATE----- diff --git a/tests/functional/ldap/configs/clickhouse/ssl/server.key b/tests/functional/ldap/configs/clickhouse/ssl/server.key new file mode 100644 index 00000000000..f0fb61ac443 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/ssl/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCz25KjqUkbyjyn +DR9tUZW7S086WNJZxVJcf26IkHCVktCeE3hIVIWiF8jgrxTW0ENOfE8tSj9XUr3L +OguJEMYyTBWPr7j6ETa51LZ49NC/mhox4n3Cuz7lz1Pik62WreksB2bThkwHWdus +TKxx5W50dGRBsYfMenpUbb0XDsZrpimrIdCKFGYSRNTtQJg0D5WTtoM90xL+SHB7 +JOldhmKZor1/QQJTf9U54bd8fpKnZfoU3i1SP9oVcSOxGZTkbZOViJIhQwXYk92F +KKF+TWElUAusc9NTfxI4v4bLIFFZ01ysjBXBum+y8+CmvIxI3GemvQArR0WGPCe6 +ki/mEkg5AgMBAAECggEATrbIBIxwDJOD2/BoUqWkDCY3dGevF8697vFuZKIiQ7PP +TX9j4vPq0DfsmDjHvAPFkTHiTQXzlroFik3LAp+uvhCCVzImmHq0IrwvZ9xtB43f +7Pkc5P6h1l3Ybo8HJ6zRIY3TuLtLxuPSuiOMTQSGRL0zq3SQ5DKuGwkz+kVjHXUN +MR2TECFwMHKQ5VLrC+7PMpsJYyOMlDAWhRfUalxC55xOXTpaN8TxNnwQ8K2ISVY5 +212Jz/a4hn4LdwxSz3Tiu95PN072K87HLWx3EdT6vW4Ge5P/A3y+smIuNAlanMnu +plHBRtpATLiTxZt/n6npyrfQVbYjSH7KWhB8hBHtaQKBgQDh9Cq1c/KtqDtE0Ccr +/r9tZNTUwBE6VP+3OJeKdEdtsfuxjOCkS1oAjgBJiSDOiWPh1DdoDeVZjPKq6pIu +Mq12OE3Doa8znfCXGbkSzEKOb2unKZMJxzrz99kXt40W5DtrqKPNb24CNqTiY8Aa +CjtcX+3weat82VRXvph6U8ltMwKBgQDLxjiQQzNoY7qvg7CwJCjf9qq8jmLK766g +1FHXopqS+dTxDLM8eJSRrpmxGWJvNeNc1uPhsKsKgotqAMdBUQTf7rSTbt4MyoH5 +bUcRLtr+0QTK9hDWMOOvleqNXha68vATkohWYfCueNsC60qD44o8RZAS6UNy3ENq +cM1cxqe84wKBgQDKkHutWnooJtajlTxY27O/nZKT/HA1bDgniMuKaz4R4Gr1PIez +on3YW3V0d0P7BP6PWRIm7bY79vkiMtLEKdiKUGWeyZdo3eHvhDb/3DCawtau8L2K +GZsHVp2//mS1Lfz7Qh8/L/NedqCQ+L4iWiPnZ3THjjwn3CoZ05ucpvrAMwKBgB54 +nay039MUVq44Owub3KDg+dcIU62U+cAC/9oG7qZbxYPmKkc4oL7IJSNecGHA5SbU +2268RFdl/gLz6tfRjbEOuOHzCjFPdvAdbysanpTMHLNc6FefJ+zxtgk9sJh0C4Jh +vxFrw9nTKKzfEl12gQ1SOaEaUIO0fEBGbe8ZpauRAoGAMAlGV+2/K4ebvAJKOVTa +dKAzQ+TD2SJmeR1HZmKDYddNqwtZlzg3v4ZhCk4eaUmGeC1Bdh8MDuB3QQvXz4Dr +vOIP4UVaOr+uM+7TgAgVnP4/K6IeJGzUDhX93pmpWhODfdu/oojEKVcpCojmEmS1 +KCBtmIrQLqzMpnBpLNuSY+Q= +-----END PRIVATE KEY----- diff --git a/tests/functional/ldap/configs/clickhouse/users.xml b/tests/functional/ldap/configs/clickhouse/users.xml new file mode 100644 index 00000000000..86b2cd9e1e3 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse/users.xml @@ -0,0 +1,133 @@ + + + + + + + + 10000000000 + + + 0 + + + random + + + + + 1 + + + + + + + + + + + + + ::/0 + + + + default + + + default + + + 1 + + + + + + + + + + + + + + + + + 3600 + + + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/tests/functional/ldap/configs/clickhouse1/config.d/macros.xml b/tests/functional/ldap/configs/clickhouse1/config.d/macros.xml new file mode 100644 index 00000000000..6cdcc1b440c --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse1/config.d/macros.xml @@ -0,0 +1,8 @@ + + + + clickhouse1 + 01 + 01 + + diff --git a/tests/functional/ldap/configs/clickhouse2/config.d/macros.xml b/tests/functional/ldap/configs/clickhouse2/config.d/macros.xml new file mode 100644 index 00000000000..a114a9ce4ab --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse2/config.d/macros.xml @@ -0,0 +1,8 @@ + + + + clickhouse2 + 01 + 02 + + diff --git a/tests/functional/ldap/configs/clickhouse3/config.d/macros.xml b/tests/functional/ldap/configs/clickhouse3/config.d/macros.xml new file mode 100644 index 00000000000..904a27b0172 --- /dev/null +++ b/tests/functional/ldap/configs/clickhouse3/config.d/macros.xml @@ -0,0 +1,8 @@ + + + + clickhouse3 + 01 + 03 + + diff --git a/tests/functional/ldap/configs/ldap1/config/export.ldif b/tests/functional/ldap/configs/ldap1/config/export.ldif new file mode 100644 index 00000000000..621dd32ca0c --- /dev/null +++ b/tests/functional/ldap/configs/ldap1/config/export.ldif @@ -0,0 +1,64 @@ +# LDIF Export for dc=company,dc=com +# Server: openldap (openldap) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 7 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on May 22, 2020 5:51 pm +# Version: 1.2.5 + +# Entry 1: dc=company,dc=com +#dn: dc=company,dc=com +#dc: company +#o: company +#objectclass: top +#objectclass: dcObject +#objectclass: organization + +# Entry 2: cn=admin,dc=company,dc=com +#dn: cn=admin,dc=company,dc=com +#cn: admin +#description: LDAP administrator +#objectclass: simpleSecurityObject +#objectclass: organizationalRole +#userpassword: {SSHA}eUEupkQCTvq9SkrxfWGSe5rX+orrjVbF + +# Entry 3: ou=groups,dc=company,dc=com +dn: ou=groups,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: groups + +# Entry 4: cn=admin,ou=groups,dc=company,dc=com +dn: cn=admin,ou=groups,dc=company,dc=com +cn: admin +gidnumber: 500 +objectclass: posixGroup +objectclass: top + +# Entry 5: cn=users,ou=groups,dc=company,dc=com +dn: cn=users,ou=groups,dc=company,dc=com +cn: users +gidnumber: 501 +objectclass: posixGroup +objectclass: top + +# Entry 6: ou=users,dc=company,dc=com +dn: ou=users,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: users + +# Entry 7: cn=user1,ou=users,dc=company,dc=com +dn: cn=user1,ou=users,dc=company,dc=com +cn: user1 +gidnumber: 501 +givenname: John +homedirectory: /home/users/user1 +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: User +uid: user1 +uidnumber: 1101 +userpassword: user1 diff --git a/tests/functional/ldap/configs/ldap2/certs/ca.crt b/tests/functional/ldap/configs/ldap2/certs/ca.crt new file mode 100644 index 00000000000..8c71e3afc91 --- /dev/null +++ b/tests/functional/ldap/configs/ldap2/certs/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDlTCCAn2gAwIBAgIUJBqw2dHM2DDCZjYSkPOESlvDH6swDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgMAk9OMQ8wDQYDVQQHDAZPdHRhd2Ex +ETAPBgNVBAoMCEFsdGluaXR5MQswCQYDVQQLDAJRQTENMAsGA1UEAwwEcm9vdDAe +Fw0yMDA2MTExOTAzNDhaFw0zMDA2MDkxOTAzNDhaMFoxCzAJBgNVBAYTAkNBMQsw +CQYDVQQIDAJPTjEPMA0GA1UEBwwGT3R0YXdhMREwDwYDVQQKDAhBbHRpbml0eTEL +MAkGA1UECwwCUUExDTALBgNVBAMMBHJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQC9Irr0zGV+HCI2fZ0ht4hR5It4Sbjz4RwZV8ENRP/+TEz8l9eK +J6ygxhKX7SMYzIs/jS9Gsq4plX1r2ujW1qRf8yLpR4+dGLP+jBRi1drj0XjZXosT +SERjWzgPauWxL9LN8+l26eBAqz6fw5e0W8WRSTgf5iGiCcKOTmaATIUjP0CdfWKK +qpktI4vhe++CXZFJ3usR+8KZ/FwwbCLJM/3J2HnbcXfcaYPYvr1tfqLudKSTbG9H +M3+AVwjctdesc/0sbd51Zsm0ClQptMbuKnDCYauGg61kNkgbgPgRmH9Pzo67DtxF +/WW+PtOzq8xLOifciQ9Piboy9QBSQZGwf4wzAgMBAAGjUzBRMB0GA1UdDgQWBBSi +njya0RDozx3OZTLYFpwqYnlpIDAfBgNVHSMEGDAWgBSinjya0RDozx3OZTLYFpwq +YnlpIDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBAD7VyFg7F +U1C25KFvtauchAOjCW6w7U/b3z1dVZvcQ88/kH1VsLUcfGixlSilUEfPTJsi7OA0 +R5BQdh2GGcjUJv4iqEFGU05KvMVmRRKn08P62+ZhJxKMxG26VzcliRZzCMkI6d0W +lFwI6nM45yeqdHVh5k4xbuJzqpbD9BtXXLI+/Ra9Fx8S9ETA3GdidpZLU5P1VLxq +UuedfqyAVWZXpr6TAURGxouRmRzul9yFzbSUex+MLEIPrstjtEwV3+tBQZJz9xAS +TVPj+Nv3LO7GCq54bdwkq1ioWbSL2hEmABkj6kdW/JwmfhGHf/2rirDVMzrTYw07 +dFJfAZC+FEsv +-----END CERTIFICATE----- diff --git a/tests/functional/ldap/configs/ldap2/certs/dhparam.pem b/tests/functional/ldap/configs/ldap2/certs/dhparam.pem new file mode 100644 index 00000000000..0a96faffd62 --- /dev/null +++ b/tests/functional/ldap/configs/ldap2/certs/dhparam.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAJitt2hhnpDViQ5ko2ipBMdjy+bZ6FR/WdZ987R7lQvBkKehPXmxtEyV +AO6ofv5CZSDJokc5bUeBOAtg0EhMTCH82uPdwQvt58jRXcxXBg4JTjkx+oW9LBv2 +FdZsbaX8+SYivmiZ0Jp8T/HBm/4DA9VBS0O5GFRS4C7dHhmSTPfDAgEC +-----END DH PARAMETERS----- diff --git a/tests/functional/ldap/configs/ldap2/certs/ldap.crt b/tests/functional/ldap/configs/ldap2/certs/ldap.crt new file mode 100644 index 00000000000..9167cbf861d --- /dev/null +++ b/tests/functional/ldap/configs/ldap2/certs/ldap.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQDCCAigCFCJ7El0ntrGktZVTYTZd+OwtcJjBMA0GCSqGSIb3DQEBCwUAMFox +CzAJBgNVBAYTAkNBMQswCQYDVQQIDAJPTjEPMA0GA1UEBwwGT3R0YXdhMREwDwYD +VQQKDAhBbHRpbml0eTELMAkGA1UECwwCUUExDTALBgNVBAMMBHJvb3QwHhcNMjAw +NjExMTkxMTQzWhcNMzAwNjA5MTkxMTQzWjBfMQswCQYDVQQGEwJDQTELMAkGA1UE +CAwCT04xDzANBgNVBAcMBk90dGF3YTERMA8GA1UECgwIQWx0aW5pdHkxCzAJBgNV +BAsMAlFBMRIwEAYDVQQDDAlvcGVubGRhcDIwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQC0Mbn//U56URavMgXm82FWP6vBdKuRydFX/L0M5XLlnAtk/IXG +/T+4t7nOBJxWmTp/xpsPtSMALE4eFJpEUEqlpVbG5DfBzVWcYOWoMeRAcHWCDkzr +PkB6I0dfF0Mm5hoaDhn+ZXjBWvoh/IlJdAnPg5mlejflJBQ7xtFC9eN6WjldXuRO +vyntGNuMfVLgITHwXuH2yZ98G0mFO6TU/9dRY/Z3D6RTSzKdb17Yk/VnG+ry92u2 +0sgXIBvhuJuC3ksWLArwwFoMl8DVa05D4O2H76goGdCcQ0KzqBV8RPXAh3UcgP2e +Zu90p2EGIhIk+sZTCkPd4dorxjL9nkRR86HdAgMBAAEwDQYJKoZIhvcNAQELBQAD +ggEBAJWiCxJaTksv/BTsh/etxlDY5eHwqStqIuiovEQ8bhGAcKJ3bfWd/YTb8DUS +hrLvXrXdOVC+U8PqPFXBpdOqcm5Dc233z52VgUCb+0EKv3lAzgKXRIo32h52skdK +NnRrCHDeDzgfEIXR4MEJ99cLEaxWyXQhremmTYWHYznry9/4NYz40gCDxHn9dJAi +KxFyDNxhtuKs58zp4PrBoo+542JurAoLPtRGOhdXpU2RkQVU/ho38HsAXDStAB5D +vAoSxPuMHKgo17ffrb0oqU3didwaA9fIsz7Mr6RxmI7X03s7hLzNBq9FCqu0U3RR +CX4zWGFNJu/ieSGVWLYKQzbYxp8= +-----END CERTIFICATE----- diff --git a/tests/functional/ldap/configs/ldap2/certs/ldap.csr b/tests/functional/ldap/configs/ldap2/certs/ldap.csr new file mode 100644 index 00000000000..bf569f727d6 --- /dev/null +++ b/tests/functional/ldap/configs/ldap2/certs/ldap.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICpDCCAYwCAQAwXzELMAkGA1UEBhMCQ0ExCzAJBgNVBAgMAk9OMQ8wDQYDVQQH +DAZPdHRhd2ExETAPBgNVBAoMCEFsdGluaXR5MQswCQYDVQQLDAJRQTESMBAGA1UE +AwwJb3BlbmxkYXAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDG5 +//1OelEWrzIF5vNhVj+rwXSrkcnRV/y9DOVy5ZwLZPyFxv0/uLe5zgScVpk6f8ab +D7UjACxOHhSaRFBKpaVWxuQ3wc1VnGDlqDHkQHB1gg5M6z5AeiNHXxdDJuYaGg4Z +/mV4wVr6IfyJSXQJz4OZpXo35SQUO8bRQvXjelo5XV7kTr8p7RjbjH1S4CEx8F7h +9smffBtJhTuk1P/XUWP2dw+kU0synW9e2JP1Zxvq8vdrttLIFyAb4bibgt5LFiwK +8MBaDJfA1WtOQ+Dth++oKBnQnENCs6gVfET1wId1HID9nmbvdKdhBiISJPrGUwpD +3eHaK8Yy/Z5EUfOh3QIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAEzIjZQOT5R7 +mEJg+RFpCSIoPn3xJ4/VMMyWqA3bTGZKpb4S6GxgsierY/87kPL7jZrMdGYB4Dc3 +2M3VWZGXlYo8vctH1zLE9VW6CzosUpl20lhdgydoCMz3RQqdJyK8aGeFTeLtk7G/ +TRCCUFUE6jaA+VtaCPCnOJSff3jUf76xguEu7dgTZgCKV7dtBqald8gIzF3D+AJJ +7pEN2UrC3UR0xpe2cj2GhndQJ+WsIyft3zpNFzAO13j8ZPibuVP7oDWcW3ixNCWC +213aeRVplJGof8Eo6llDxP+6Fwp1YmOoQmwB1Xm3t4ADn7FLJ14LONLB7q40KviG +RyLyqu3IVOI= +-----END CERTIFICATE REQUEST----- diff --git a/tests/functional/ldap/configs/ldap2/certs/ldap.key b/tests/functional/ldap/configs/ldap2/certs/ldap.key new file mode 100644 index 00000000000..5ab3a3f8b59 --- /dev/null +++ b/tests/functional/ldap/configs/ldap2/certs/ldap.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAtDG5//1OelEWrzIF5vNhVj+rwXSrkcnRV/y9DOVy5ZwLZPyF +xv0/uLe5zgScVpk6f8abD7UjACxOHhSaRFBKpaVWxuQ3wc1VnGDlqDHkQHB1gg5M +6z5AeiNHXxdDJuYaGg4Z/mV4wVr6IfyJSXQJz4OZpXo35SQUO8bRQvXjelo5XV7k +Tr8p7RjbjH1S4CEx8F7h9smffBtJhTuk1P/XUWP2dw+kU0synW9e2JP1Zxvq8vdr +ttLIFyAb4bibgt5LFiwK8MBaDJfA1WtOQ+Dth++oKBnQnENCs6gVfET1wId1HID9 +nmbvdKdhBiISJPrGUwpD3eHaK8Yy/Z5EUfOh3QIDAQABAoIBADugMMIKWcuTxYPX +c6iGZHEbxIPRTWyCcalB0nTQAAMGbabPAJ1l8432DZ+kWu806OybFXhPIfPOtVKy +0pFEWE8TtPE/V0vj3C5Qye2sBLFmBRwyCzXUdZV00wseMXRPs9dnTyalAR5KMnbI +j80kfpKSI2dkV9aU57UYBuq3Xrx/TCGItwL769D4ZZW9BvbpiTZApQQFZ0gwUFFn +btPXGU9Ti8H4mfBuZWL+5CaZdqOo76+CXvMPaUK0F9MJp4yX3XxQLRNH3qz/Tyn7 +h7QOOo0XTqoUmzRw0N9QRVH5LRdSE5yq3aF9aFKjNW59exz+62pufOFadngzkpkn +OKCzgWkCgYEA4mOWWMzdYwMn3GtfG7whqlqy7wOmMkNb81zTDQejHBV98dnj0AHr +deurfKWzHrAh3DXo6tFeqUIgXabhBPS/0dEx/S5sgLFmuUZP05EUYahfWBgzzmM9 +C6Oe5xIMLzxsZCJczolsfkEsoFe4o0vkvuLYoQrQL7InzewcDy8cUxsCgYEAy8Na +YCnanSNDY03Bulcni+5sF+opaHseeki1pv3nlw8TwsWuZF9ApS+yL7ck9jJjxBRR +RC3KGmpoqIr0vTmUYS946ngQWXPE90zfuhJfM+NRv/q0oCjH0qAcxRbTkls5On9v +oxJ8rO7gD6K85eHqasWdbCVzdZrobOXzay37tmcCgYBfyUUmw190cjReZauzH3Gb +E48b5A5gu/Fe0cqWe8G+szU7rDZgnz9SAGnpbm6QMHPTKZgoKngD42+wUFhq8Wdr +zjh5aDgOZ4EQKTjDSmI2Q7g7nNnmnESK9SrZl+BB6C3wXD2qQaj+7nKEUTlVFlpt +jaucz+dwFtASp7Djl8pDOwKBgEtr2c3ycArt/ImLRIP2spqm+7e2YvFbcSKOOz6+ +iLRvTj8v8KcSYtlB2FC1F6dRa4AujQ4RbNduP6LzHDfWUkfOzJDtNBAIPAXVnJJB +LqAEKkRHRghqT9x0i3GgS1vHDF3MwcO4mhFgserXr9ffUWeIEgbvrdcAKbv1Oa6Y +bK1NAoGAGPm8ISmboDJynjBl9wMrkcy23Pwg9kmyocdWUHh0zMLDKriZNKYB6u/U +C+/RTfkohPoHPzkeqWiHp7z3JhMItYUfTkNW6vMCxEGc0NEN6ZyMIjtiDPGN1n6O +E7jmODFmj1AQICQGdV5SHp+yKvKyb0YHKyDwETbs4SZBXxVvjEw= +-----END RSA PRIVATE KEY----- diff --git a/tests/functional/ldap/configs/ldap2/config/export.ldif b/tests/functional/ldap/configs/ldap2/config/export.ldif new file mode 100644 index 00000000000..6766aaae6f1 --- /dev/null +++ b/tests/functional/ldap/configs/ldap2/config/export.ldif @@ -0,0 +1,64 @@ +# LDIF Export for dc=company,dc=com +# Server: openldap (openldap) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 7 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on May 22, 2020 5:51 pm +# Version: 1.2.5 + +# Entry 1: dc=company,dc=com +#dn: dc=company,dc=com +#dc: company +#o: company +#objectclass: top +#objectclass: dcObject +#objectclass: organization + +# Entry 2: cn=admin,dc=company,dc=com +#dn: cn=admin,dc=company,dc=com +#cn: admin +#description: LDAP administrator +#objectclass: simpleSecurityObject +#objectclass: organizationalRole +#userpassword: {SSHA}eUEupkQCTvq9SkrxfWGSe5rX+orrjVbF + +# Entry 3: ou=groups,dc=company,dc=com +dn: ou=groups,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: groups + +# Entry 4: cn=admin,ou=groups,dc=company,dc=com +dn: cn=admin,ou=groups,dc=company,dc=com +cn: admin +gidnumber: 500 +objectclass: posixGroup +objectclass: top + +# Entry 5: cn=users,ou=groups,dc=company,dc=com +dn: cn=users,ou=groups,dc=company,dc=com +cn: users +gidnumber: 501 +objectclass: posixGroup +objectclass: top + +# Entry 6: ou=users,dc=company,dc=com +dn: ou=users,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: users + +# Entry 7: cn=user2,ou=users,dc=company,dc=com +dn: cn=user2,ou=users,dc=company,dc=com +cn: user2 +gidnumber: 501 +givenname: John +homedirectory: /home/users/user2 +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: User +uid: user2 +uidnumber: 1002 +userpassword: user2 diff --git a/tests/functional/ldap/configs/ldap3/certs/ca.crt b/tests/functional/ldap/configs/ldap3/certs/ca.crt new file mode 100644 index 00000000000..8c71e3afc91 --- /dev/null +++ b/tests/functional/ldap/configs/ldap3/certs/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDlTCCAn2gAwIBAgIUJBqw2dHM2DDCZjYSkPOESlvDH6swDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgMAk9OMQ8wDQYDVQQHDAZPdHRhd2Ex +ETAPBgNVBAoMCEFsdGluaXR5MQswCQYDVQQLDAJRQTENMAsGA1UEAwwEcm9vdDAe +Fw0yMDA2MTExOTAzNDhaFw0zMDA2MDkxOTAzNDhaMFoxCzAJBgNVBAYTAkNBMQsw +CQYDVQQIDAJPTjEPMA0GA1UEBwwGT3R0YXdhMREwDwYDVQQKDAhBbHRpbml0eTEL +MAkGA1UECwwCUUExDTALBgNVBAMMBHJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQC9Irr0zGV+HCI2fZ0ht4hR5It4Sbjz4RwZV8ENRP/+TEz8l9eK +J6ygxhKX7SMYzIs/jS9Gsq4plX1r2ujW1qRf8yLpR4+dGLP+jBRi1drj0XjZXosT +SERjWzgPauWxL9LN8+l26eBAqz6fw5e0W8WRSTgf5iGiCcKOTmaATIUjP0CdfWKK +qpktI4vhe++CXZFJ3usR+8KZ/FwwbCLJM/3J2HnbcXfcaYPYvr1tfqLudKSTbG9H +M3+AVwjctdesc/0sbd51Zsm0ClQptMbuKnDCYauGg61kNkgbgPgRmH9Pzo67DtxF +/WW+PtOzq8xLOifciQ9Piboy9QBSQZGwf4wzAgMBAAGjUzBRMB0GA1UdDgQWBBSi +njya0RDozx3OZTLYFpwqYnlpIDAfBgNVHSMEGDAWgBSinjya0RDozx3OZTLYFpwq +YnlpIDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBAD7VyFg7F +U1C25KFvtauchAOjCW6w7U/b3z1dVZvcQ88/kH1VsLUcfGixlSilUEfPTJsi7OA0 +R5BQdh2GGcjUJv4iqEFGU05KvMVmRRKn08P62+ZhJxKMxG26VzcliRZzCMkI6d0W +lFwI6nM45yeqdHVh5k4xbuJzqpbD9BtXXLI+/Ra9Fx8S9ETA3GdidpZLU5P1VLxq +UuedfqyAVWZXpr6TAURGxouRmRzul9yFzbSUex+MLEIPrstjtEwV3+tBQZJz9xAS +TVPj+Nv3LO7GCq54bdwkq1ioWbSL2hEmABkj6kdW/JwmfhGHf/2rirDVMzrTYw07 +dFJfAZC+FEsv +-----END CERTIFICATE----- diff --git a/tests/functional/ldap/configs/ldap3/certs/dhparam.pem b/tests/functional/ldap/configs/ldap3/certs/dhparam.pem new file mode 100644 index 00000000000..0a96faffd62 --- /dev/null +++ b/tests/functional/ldap/configs/ldap3/certs/dhparam.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAJitt2hhnpDViQ5ko2ipBMdjy+bZ6FR/WdZ987R7lQvBkKehPXmxtEyV +AO6ofv5CZSDJokc5bUeBOAtg0EhMTCH82uPdwQvt58jRXcxXBg4JTjkx+oW9LBv2 +FdZsbaX8+SYivmiZ0Jp8T/HBm/4DA9VBS0O5GFRS4C7dHhmSTPfDAgEC +-----END DH PARAMETERS----- diff --git a/tests/functional/ldap/configs/ldap3/certs/ldap.crt b/tests/functional/ldap/configs/ldap3/certs/ldap.crt new file mode 100644 index 00000000000..9167cbf861d --- /dev/null +++ b/tests/functional/ldap/configs/ldap3/certs/ldap.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQDCCAigCFCJ7El0ntrGktZVTYTZd+OwtcJjBMA0GCSqGSIb3DQEBCwUAMFox +CzAJBgNVBAYTAkNBMQswCQYDVQQIDAJPTjEPMA0GA1UEBwwGT3R0YXdhMREwDwYD +VQQKDAhBbHRpbml0eTELMAkGA1UECwwCUUExDTALBgNVBAMMBHJvb3QwHhcNMjAw +NjExMTkxMTQzWhcNMzAwNjA5MTkxMTQzWjBfMQswCQYDVQQGEwJDQTELMAkGA1UE +CAwCT04xDzANBgNVBAcMBk90dGF3YTERMA8GA1UECgwIQWx0aW5pdHkxCzAJBgNV +BAsMAlFBMRIwEAYDVQQDDAlvcGVubGRhcDIwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQC0Mbn//U56URavMgXm82FWP6vBdKuRydFX/L0M5XLlnAtk/IXG +/T+4t7nOBJxWmTp/xpsPtSMALE4eFJpEUEqlpVbG5DfBzVWcYOWoMeRAcHWCDkzr +PkB6I0dfF0Mm5hoaDhn+ZXjBWvoh/IlJdAnPg5mlejflJBQ7xtFC9eN6WjldXuRO +vyntGNuMfVLgITHwXuH2yZ98G0mFO6TU/9dRY/Z3D6RTSzKdb17Yk/VnG+ry92u2 +0sgXIBvhuJuC3ksWLArwwFoMl8DVa05D4O2H76goGdCcQ0KzqBV8RPXAh3UcgP2e +Zu90p2EGIhIk+sZTCkPd4dorxjL9nkRR86HdAgMBAAEwDQYJKoZIhvcNAQELBQAD +ggEBAJWiCxJaTksv/BTsh/etxlDY5eHwqStqIuiovEQ8bhGAcKJ3bfWd/YTb8DUS +hrLvXrXdOVC+U8PqPFXBpdOqcm5Dc233z52VgUCb+0EKv3lAzgKXRIo32h52skdK +NnRrCHDeDzgfEIXR4MEJ99cLEaxWyXQhremmTYWHYznry9/4NYz40gCDxHn9dJAi +KxFyDNxhtuKs58zp4PrBoo+542JurAoLPtRGOhdXpU2RkQVU/ho38HsAXDStAB5D +vAoSxPuMHKgo17ffrb0oqU3didwaA9fIsz7Mr6RxmI7X03s7hLzNBq9FCqu0U3RR +CX4zWGFNJu/ieSGVWLYKQzbYxp8= +-----END CERTIFICATE----- diff --git a/tests/functional/ldap/configs/ldap3/certs/ldap.csr b/tests/functional/ldap/configs/ldap3/certs/ldap.csr new file mode 100644 index 00000000000..bf569f727d6 --- /dev/null +++ b/tests/functional/ldap/configs/ldap3/certs/ldap.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICpDCCAYwCAQAwXzELMAkGA1UEBhMCQ0ExCzAJBgNVBAgMAk9OMQ8wDQYDVQQH +DAZPdHRhd2ExETAPBgNVBAoMCEFsdGluaXR5MQswCQYDVQQLDAJRQTESMBAGA1UE +AwwJb3BlbmxkYXAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDG5 +//1OelEWrzIF5vNhVj+rwXSrkcnRV/y9DOVy5ZwLZPyFxv0/uLe5zgScVpk6f8ab +D7UjACxOHhSaRFBKpaVWxuQ3wc1VnGDlqDHkQHB1gg5M6z5AeiNHXxdDJuYaGg4Z +/mV4wVr6IfyJSXQJz4OZpXo35SQUO8bRQvXjelo5XV7kTr8p7RjbjH1S4CEx8F7h +9smffBtJhTuk1P/XUWP2dw+kU0synW9e2JP1Zxvq8vdrttLIFyAb4bibgt5LFiwK +8MBaDJfA1WtOQ+Dth++oKBnQnENCs6gVfET1wId1HID9nmbvdKdhBiISJPrGUwpD +3eHaK8Yy/Z5EUfOh3QIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAEzIjZQOT5R7 +mEJg+RFpCSIoPn3xJ4/VMMyWqA3bTGZKpb4S6GxgsierY/87kPL7jZrMdGYB4Dc3 +2M3VWZGXlYo8vctH1zLE9VW6CzosUpl20lhdgydoCMz3RQqdJyK8aGeFTeLtk7G/ +TRCCUFUE6jaA+VtaCPCnOJSff3jUf76xguEu7dgTZgCKV7dtBqald8gIzF3D+AJJ +7pEN2UrC3UR0xpe2cj2GhndQJ+WsIyft3zpNFzAO13j8ZPibuVP7oDWcW3ixNCWC +213aeRVplJGof8Eo6llDxP+6Fwp1YmOoQmwB1Xm3t4ADn7FLJ14LONLB7q40KviG +RyLyqu3IVOI= +-----END CERTIFICATE REQUEST----- diff --git a/tests/functional/ldap/configs/ldap3/certs/ldap.key b/tests/functional/ldap/configs/ldap3/certs/ldap.key new file mode 100644 index 00000000000..5ab3a3f8b59 --- /dev/null +++ b/tests/functional/ldap/configs/ldap3/certs/ldap.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAtDG5//1OelEWrzIF5vNhVj+rwXSrkcnRV/y9DOVy5ZwLZPyF +xv0/uLe5zgScVpk6f8abD7UjACxOHhSaRFBKpaVWxuQ3wc1VnGDlqDHkQHB1gg5M +6z5AeiNHXxdDJuYaGg4Z/mV4wVr6IfyJSXQJz4OZpXo35SQUO8bRQvXjelo5XV7k +Tr8p7RjbjH1S4CEx8F7h9smffBtJhTuk1P/XUWP2dw+kU0synW9e2JP1Zxvq8vdr +ttLIFyAb4bibgt5LFiwK8MBaDJfA1WtOQ+Dth++oKBnQnENCs6gVfET1wId1HID9 +nmbvdKdhBiISJPrGUwpD3eHaK8Yy/Z5EUfOh3QIDAQABAoIBADugMMIKWcuTxYPX +c6iGZHEbxIPRTWyCcalB0nTQAAMGbabPAJ1l8432DZ+kWu806OybFXhPIfPOtVKy +0pFEWE8TtPE/V0vj3C5Qye2sBLFmBRwyCzXUdZV00wseMXRPs9dnTyalAR5KMnbI +j80kfpKSI2dkV9aU57UYBuq3Xrx/TCGItwL769D4ZZW9BvbpiTZApQQFZ0gwUFFn +btPXGU9Ti8H4mfBuZWL+5CaZdqOo76+CXvMPaUK0F9MJp4yX3XxQLRNH3qz/Tyn7 +h7QOOo0XTqoUmzRw0N9QRVH5LRdSE5yq3aF9aFKjNW59exz+62pufOFadngzkpkn +OKCzgWkCgYEA4mOWWMzdYwMn3GtfG7whqlqy7wOmMkNb81zTDQejHBV98dnj0AHr +deurfKWzHrAh3DXo6tFeqUIgXabhBPS/0dEx/S5sgLFmuUZP05EUYahfWBgzzmM9 +C6Oe5xIMLzxsZCJczolsfkEsoFe4o0vkvuLYoQrQL7InzewcDy8cUxsCgYEAy8Na +YCnanSNDY03Bulcni+5sF+opaHseeki1pv3nlw8TwsWuZF9ApS+yL7ck9jJjxBRR +RC3KGmpoqIr0vTmUYS946ngQWXPE90zfuhJfM+NRv/q0oCjH0qAcxRbTkls5On9v +oxJ8rO7gD6K85eHqasWdbCVzdZrobOXzay37tmcCgYBfyUUmw190cjReZauzH3Gb +E48b5A5gu/Fe0cqWe8G+szU7rDZgnz9SAGnpbm6QMHPTKZgoKngD42+wUFhq8Wdr +zjh5aDgOZ4EQKTjDSmI2Q7g7nNnmnESK9SrZl+BB6C3wXD2qQaj+7nKEUTlVFlpt +jaucz+dwFtASp7Djl8pDOwKBgEtr2c3ycArt/ImLRIP2spqm+7e2YvFbcSKOOz6+ +iLRvTj8v8KcSYtlB2FC1F6dRa4AujQ4RbNduP6LzHDfWUkfOzJDtNBAIPAXVnJJB +LqAEKkRHRghqT9x0i3GgS1vHDF3MwcO4mhFgserXr9ffUWeIEgbvrdcAKbv1Oa6Y +bK1NAoGAGPm8ISmboDJynjBl9wMrkcy23Pwg9kmyocdWUHh0zMLDKriZNKYB6u/U +C+/RTfkohPoHPzkeqWiHp7z3JhMItYUfTkNW6vMCxEGc0NEN6ZyMIjtiDPGN1n6O +E7jmODFmj1AQICQGdV5SHp+yKvKyb0YHKyDwETbs4SZBXxVvjEw= +-----END RSA PRIVATE KEY----- diff --git a/tests/functional/ldap/configs/ldap3/config/export.ldif b/tests/functional/ldap/configs/ldap3/config/export.ldif new file mode 100644 index 00000000000..6ac9a995efd --- /dev/null +++ b/tests/functional/ldap/configs/ldap3/config/export.ldif @@ -0,0 +1,64 @@ +# LDIF Export for dc=company,dc=com +# Server: openldap (openldap) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 7 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on May 22, 2020 5:51 pm +# Version: 1.2.5 + +# Entry 1: dc=company,dc=com +#dn: dc=company,dc=com +#dc: company +#o: company +#objectclass: top +#objectclass: dcObject +#objectclass: organization + +# Entry 2: cn=admin,dc=company,dc=com +#dn: cn=admin,dc=company,dc=com +#cn: admin +#description: LDAP administrator +#objectclass: simpleSecurityObject +#objectclass: organizationalRole +#userpassword: {SSHA}eUEupkQCTvq9SkrxfWGSe5rX+orrjVbF + +# Entry 3: ou=groups,dc=company,dc=com +dn: ou=groups,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: groups + +# Entry 4: cn=admin,ou=groups,dc=company,dc=com +dn: cn=admin,ou=groups,dc=company,dc=com +cn: admin +gidnumber: 500 +objectclass: posixGroup +objectclass: top + +# Entry 5: cn=users,ou=groups,dc=company,dc=com +dn: cn=users,ou=groups,dc=company,dc=com +cn: users +gidnumber: 501 +objectclass: posixGroup +objectclass: top + +# Entry 6: ou=users,dc=company,dc=com +dn: ou=users,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: users + +# Entry 7: cn=user3,ou=users,dc=company,dc=com +dn: cn=user3,ou=users,dc=company,dc=com +cn: user3 +gidnumber: 501 +givenname: John +homedirectory: /home/users/user3 +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: User +uid: user3 +uidnumber: 1003 +userpassword: user3 diff --git a/tests/functional/ldap/configs/ldap4/config/export.ldif b/tests/functional/ldap/configs/ldap4/config/export.ldif new file mode 100644 index 00000000000..36afdb4e350 --- /dev/null +++ b/tests/functional/ldap/configs/ldap4/config/export.ldif @@ -0,0 +1,64 @@ +# LDIF Export for dc=company,dc=com +# Server: openldap (openldap) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 7 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on May 22, 2020 5:51 pm +# Version: 1.2.5 + +# Entry 1: dc=company,dc=com +#dn: dc=company,dc=com +#dc: company +#o: company +#objectclass: top +#objectclass: dcObject +#objectclass: organization + +# Entry 2: cn=admin,dc=company,dc=com +#dn: cn=admin,dc=company,dc=com +#cn: admin +#description: LDAP administrator +#objectclass: simpleSecurityObject +#objectclass: organizationalRole +#userpassword: {SSHA}eUEupkQCTvq9SkrxfWGSe5rX+orrjVbF + +# Entry 3: ou=groups,dc=company,dc=com +dn: ou=groups,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: groups + +# Entry 4: cn=admin,ou=groups,dc=company,dc=com +dn: cn=admin,ou=groups,dc=company,dc=com +cn: admin +gidnumber: 500 +objectclass: posixGroup +objectclass: top + +# Entry 5: cn=users,ou=groups,dc=company,dc=com +dn: cn=users,ou=groups,dc=company,dc=com +cn: users +gidnumber: 501 +objectclass: posixGroup +objectclass: top + +# Entry 6: ou=users,dc=company,dc=com +dn: ou=users,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: users + +# Entry 7: cn=user4,ou=users,dc=company,dc=com +dn: cn=user4,ou=users,dc=company,dc=com +cn: user4 +gidnumber: 501 +givenname: John +homedirectory: /home/users/user4 +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: User +uid: user4 +uidnumber: 1004 +userpassword: user4 diff --git a/tests/functional/ldap/configs/ldap5/config/export.ldif b/tests/functional/ldap/configs/ldap5/config/export.ldif new file mode 100644 index 00000000000..bc3d2ff75fc --- /dev/null +++ b/tests/functional/ldap/configs/ldap5/config/export.ldif @@ -0,0 +1,64 @@ +# LDIF Export for dc=company,dc=com +# Server: openldap (openldap) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 7 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on May 22, 2020 5:51 pm +# Version: 1.2.5 + +# Entry 1: dc=company,dc=com +#dn: dc=company,dc=com +#dc: company +#o: company +#objectclass: top +#objectclass: dcObject +#objectclass: organization + +# Entry 2: cn=admin,dc=company,dc=com +#dn: cn=admin,dc=company,dc=com +#cn: admin +#description: LDAP administrator +#objectclass: simpleSecurityObject +#objectclass: organizationalRole +#userpassword: {SSHA}eUEupkQCTvq9SkrxfWGSe5rX+orrjVbF + +# Entry 3: ou=groups,dc=company,dc=com +dn: ou=groups,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: groups + +# Entry 4: cn=admin,ou=groups,dc=company,dc=com +dn: cn=admin,ou=groups,dc=company,dc=com +cn: admin +gidnumber: 500 +objectclass: posixGroup +objectclass: top + +# Entry 5: cn=users,ou=groups,dc=company,dc=com +dn: cn=users,ou=groups,dc=company,dc=com +cn: users +gidnumber: 501 +objectclass: posixGroup +objectclass: top + +# Entry 6: ou=users,dc=company,dc=com +dn: ou=users,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: users + +# Entry 7: cn=user5,ou=users,dc=company,dc=com +dn: cn=user5,ou=users,dc=company,dc=com +cn: user5 +gidnumber: 501 +givenname: John +homedirectory: /home/users/user5 +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: User +uid: user5 +uidnumber: 1005 +userpassword: user5 diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/ca.crt b/tests/functional/ldap/configs/ldap5/ldap2/certs/ca.crt new file mode 100644 index 00000000000..8c71e3afc91 --- /dev/null +++ b/tests/functional/ldap/configs/ldap5/ldap2/certs/ca.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDlTCCAn2gAwIBAgIUJBqw2dHM2DDCZjYSkPOESlvDH6swDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCQ0ExCzAJBgNVBAgMAk9OMQ8wDQYDVQQHDAZPdHRhd2Ex +ETAPBgNVBAoMCEFsdGluaXR5MQswCQYDVQQLDAJRQTENMAsGA1UEAwwEcm9vdDAe +Fw0yMDA2MTExOTAzNDhaFw0zMDA2MDkxOTAzNDhaMFoxCzAJBgNVBAYTAkNBMQsw +CQYDVQQIDAJPTjEPMA0GA1UEBwwGT3R0YXdhMREwDwYDVQQKDAhBbHRpbml0eTEL +MAkGA1UECwwCUUExDTALBgNVBAMMBHJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQC9Irr0zGV+HCI2fZ0ht4hR5It4Sbjz4RwZV8ENRP/+TEz8l9eK +J6ygxhKX7SMYzIs/jS9Gsq4plX1r2ujW1qRf8yLpR4+dGLP+jBRi1drj0XjZXosT +SERjWzgPauWxL9LN8+l26eBAqz6fw5e0W8WRSTgf5iGiCcKOTmaATIUjP0CdfWKK +qpktI4vhe++CXZFJ3usR+8KZ/FwwbCLJM/3J2HnbcXfcaYPYvr1tfqLudKSTbG9H +M3+AVwjctdesc/0sbd51Zsm0ClQptMbuKnDCYauGg61kNkgbgPgRmH9Pzo67DtxF +/WW+PtOzq8xLOifciQ9Piboy9QBSQZGwf4wzAgMBAAGjUzBRMB0GA1UdDgQWBBSi +njya0RDozx3OZTLYFpwqYnlpIDAfBgNVHSMEGDAWgBSinjya0RDozx3OZTLYFpwq +YnlpIDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBAD7VyFg7F +U1C25KFvtauchAOjCW6w7U/b3z1dVZvcQ88/kH1VsLUcfGixlSilUEfPTJsi7OA0 +R5BQdh2GGcjUJv4iqEFGU05KvMVmRRKn08P62+ZhJxKMxG26VzcliRZzCMkI6d0W +lFwI6nM45yeqdHVh5k4xbuJzqpbD9BtXXLI+/Ra9Fx8S9ETA3GdidpZLU5P1VLxq +UuedfqyAVWZXpr6TAURGxouRmRzul9yFzbSUex+MLEIPrstjtEwV3+tBQZJz9xAS +TVPj+Nv3LO7GCq54bdwkq1ioWbSL2hEmABkj6kdW/JwmfhGHf/2rirDVMzrTYw07 +dFJfAZC+FEsv +-----END CERTIFICATE----- diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/dhparam.pem b/tests/functional/ldap/configs/ldap5/ldap2/certs/dhparam.pem new file mode 100644 index 00000000000..0a96faffd62 --- /dev/null +++ b/tests/functional/ldap/configs/ldap5/ldap2/certs/dhparam.pem @@ -0,0 +1,5 @@ +-----BEGIN DH PARAMETERS----- +MIGHAoGBAJitt2hhnpDViQ5ko2ipBMdjy+bZ6FR/WdZ987R7lQvBkKehPXmxtEyV +AO6ofv5CZSDJokc5bUeBOAtg0EhMTCH82uPdwQvt58jRXcxXBg4JTjkx+oW9LBv2 +FdZsbaX8+SYivmiZ0Jp8T/HBm/4DA9VBS0O5GFRS4C7dHhmSTPfDAgEC +-----END DH PARAMETERS----- diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.crt b/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.crt new file mode 100644 index 00000000000..9167cbf861d --- /dev/null +++ b/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQDCCAigCFCJ7El0ntrGktZVTYTZd+OwtcJjBMA0GCSqGSIb3DQEBCwUAMFox +CzAJBgNVBAYTAkNBMQswCQYDVQQIDAJPTjEPMA0GA1UEBwwGT3R0YXdhMREwDwYD +VQQKDAhBbHRpbml0eTELMAkGA1UECwwCUUExDTALBgNVBAMMBHJvb3QwHhcNMjAw +NjExMTkxMTQzWhcNMzAwNjA5MTkxMTQzWjBfMQswCQYDVQQGEwJDQTELMAkGA1UE +CAwCT04xDzANBgNVBAcMBk90dGF3YTERMA8GA1UECgwIQWx0aW5pdHkxCzAJBgNV +BAsMAlFBMRIwEAYDVQQDDAlvcGVubGRhcDIwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQC0Mbn//U56URavMgXm82FWP6vBdKuRydFX/L0M5XLlnAtk/IXG +/T+4t7nOBJxWmTp/xpsPtSMALE4eFJpEUEqlpVbG5DfBzVWcYOWoMeRAcHWCDkzr +PkB6I0dfF0Mm5hoaDhn+ZXjBWvoh/IlJdAnPg5mlejflJBQ7xtFC9eN6WjldXuRO +vyntGNuMfVLgITHwXuH2yZ98G0mFO6TU/9dRY/Z3D6RTSzKdb17Yk/VnG+ry92u2 +0sgXIBvhuJuC3ksWLArwwFoMl8DVa05D4O2H76goGdCcQ0KzqBV8RPXAh3UcgP2e +Zu90p2EGIhIk+sZTCkPd4dorxjL9nkRR86HdAgMBAAEwDQYJKoZIhvcNAQELBQAD +ggEBAJWiCxJaTksv/BTsh/etxlDY5eHwqStqIuiovEQ8bhGAcKJ3bfWd/YTb8DUS +hrLvXrXdOVC+U8PqPFXBpdOqcm5Dc233z52VgUCb+0EKv3lAzgKXRIo32h52skdK +NnRrCHDeDzgfEIXR4MEJ99cLEaxWyXQhremmTYWHYznry9/4NYz40gCDxHn9dJAi +KxFyDNxhtuKs58zp4PrBoo+542JurAoLPtRGOhdXpU2RkQVU/ho38HsAXDStAB5D +vAoSxPuMHKgo17ffrb0oqU3didwaA9fIsz7Mr6RxmI7X03s7hLzNBq9FCqu0U3RR +CX4zWGFNJu/ieSGVWLYKQzbYxp8= +-----END CERTIFICATE----- diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.csr b/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.csr new file mode 100644 index 00000000000..bf569f727d6 --- /dev/null +++ b/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.csr @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICpDCCAYwCAQAwXzELMAkGA1UEBhMCQ0ExCzAJBgNVBAgMAk9OMQ8wDQYDVQQH +DAZPdHRhd2ExETAPBgNVBAoMCEFsdGluaXR5MQswCQYDVQQLDAJRQTESMBAGA1UE +AwwJb3BlbmxkYXAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDG5 +//1OelEWrzIF5vNhVj+rwXSrkcnRV/y9DOVy5ZwLZPyFxv0/uLe5zgScVpk6f8ab +D7UjACxOHhSaRFBKpaVWxuQ3wc1VnGDlqDHkQHB1gg5M6z5AeiNHXxdDJuYaGg4Z +/mV4wVr6IfyJSXQJz4OZpXo35SQUO8bRQvXjelo5XV7kTr8p7RjbjH1S4CEx8F7h +9smffBtJhTuk1P/XUWP2dw+kU0synW9e2JP1Zxvq8vdrttLIFyAb4bibgt5LFiwK +8MBaDJfA1WtOQ+Dth++oKBnQnENCs6gVfET1wId1HID9nmbvdKdhBiISJPrGUwpD +3eHaK8Yy/Z5EUfOh3QIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAEzIjZQOT5R7 +mEJg+RFpCSIoPn3xJ4/VMMyWqA3bTGZKpb4S6GxgsierY/87kPL7jZrMdGYB4Dc3 +2M3VWZGXlYo8vctH1zLE9VW6CzosUpl20lhdgydoCMz3RQqdJyK8aGeFTeLtk7G/ +TRCCUFUE6jaA+VtaCPCnOJSff3jUf76xguEu7dgTZgCKV7dtBqald8gIzF3D+AJJ +7pEN2UrC3UR0xpe2cj2GhndQJ+WsIyft3zpNFzAO13j8ZPibuVP7oDWcW3ixNCWC +213aeRVplJGof8Eo6llDxP+6Fwp1YmOoQmwB1Xm3t4ADn7FLJ14LONLB7q40KviG +RyLyqu3IVOI= +-----END CERTIFICATE REQUEST----- diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.key b/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.key new file mode 100644 index 00000000000..5ab3a3f8b59 --- /dev/null +++ b/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAtDG5//1OelEWrzIF5vNhVj+rwXSrkcnRV/y9DOVy5ZwLZPyF +xv0/uLe5zgScVpk6f8abD7UjACxOHhSaRFBKpaVWxuQ3wc1VnGDlqDHkQHB1gg5M +6z5AeiNHXxdDJuYaGg4Z/mV4wVr6IfyJSXQJz4OZpXo35SQUO8bRQvXjelo5XV7k +Tr8p7RjbjH1S4CEx8F7h9smffBtJhTuk1P/XUWP2dw+kU0synW9e2JP1Zxvq8vdr +ttLIFyAb4bibgt5LFiwK8MBaDJfA1WtOQ+Dth++oKBnQnENCs6gVfET1wId1HID9 +nmbvdKdhBiISJPrGUwpD3eHaK8Yy/Z5EUfOh3QIDAQABAoIBADugMMIKWcuTxYPX +c6iGZHEbxIPRTWyCcalB0nTQAAMGbabPAJ1l8432DZ+kWu806OybFXhPIfPOtVKy +0pFEWE8TtPE/V0vj3C5Qye2sBLFmBRwyCzXUdZV00wseMXRPs9dnTyalAR5KMnbI +j80kfpKSI2dkV9aU57UYBuq3Xrx/TCGItwL769D4ZZW9BvbpiTZApQQFZ0gwUFFn +btPXGU9Ti8H4mfBuZWL+5CaZdqOo76+CXvMPaUK0F9MJp4yX3XxQLRNH3qz/Tyn7 +h7QOOo0XTqoUmzRw0N9QRVH5LRdSE5yq3aF9aFKjNW59exz+62pufOFadngzkpkn +OKCzgWkCgYEA4mOWWMzdYwMn3GtfG7whqlqy7wOmMkNb81zTDQejHBV98dnj0AHr +deurfKWzHrAh3DXo6tFeqUIgXabhBPS/0dEx/S5sgLFmuUZP05EUYahfWBgzzmM9 +C6Oe5xIMLzxsZCJczolsfkEsoFe4o0vkvuLYoQrQL7InzewcDy8cUxsCgYEAy8Na +YCnanSNDY03Bulcni+5sF+opaHseeki1pv3nlw8TwsWuZF9ApS+yL7ck9jJjxBRR +RC3KGmpoqIr0vTmUYS946ngQWXPE90zfuhJfM+NRv/q0oCjH0qAcxRbTkls5On9v +oxJ8rO7gD6K85eHqasWdbCVzdZrobOXzay37tmcCgYBfyUUmw190cjReZauzH3Gb +E48b5A5gu/Fe0cqWe8G+szU7rDZgnz9SAGnpbm6QMHPTKZgoKngD42+wUFhq8Wdr +zjh5aDgOZ4EQKTjDSmI2Q7g7nNnmnESK9SrZl+BB6C3wXD2qQaj+7nKEUTlVFlpt +jaucz+dwFtASp7Djl8pDOwKBgEtr2c3ycArt/ImLRIP2spqm+7e2YvFbcSKOOz6+ +iLRvTj8v8KcSYtlB2FC1F6dRa4AujQ4RbNduP6LzHDfWUkfOzJDtNBAIPAXVnJJB +LqAEKkRHRghqT9x0i3GgS1vHDF3MwcO4mhFgserXr9ffUWeIEgbvrdcAKbv1Oa6Y +bK1NAoGAGPm8ISmboDJynjBl9wMrkcy23Pwg9kmyocdWUHh0zMLDKriZNKYB6u/U +C+/RTfkohPoHPzkeqWiHp7z3JhMItYUfTkNW6vMCxEGc0NEN6ZyMIjtiDPGN1n6O +E7jmODFmj1AQICQGdV5SHp+yKvKyb0YHKyDwETbs4SZBXxVvjEw= +-----END RSA PRIVATE KEY----- diff --git a/tests/functional/ldap/configs/ldap5/ldap2/config/export.ldif b/tests/functional/ldap/configs/ldap5/ldap2/config/export.ldif new file mode 100644 index 00000000000..c6470176a5e --- /dev/null +++ b/tests/functional/ldap/configs/ldap5/ldap2/config/export.ldif @@ -0,0 +1,64 @@ +# LDIF Export for dc=company,dc=com +# Server: openldap (openldap) +# Search Scope: sub +# Search Filter: (objectClass=*) +# Total Entries: 7 +# +# Generated by phpLDAPadmin (http://phpldapadmin.sourceforge.net) on May 22, 2020 5:51 pm +# Version: 1.2.5 + +# Entry 1: dc=company,dc=com +#dn: dc=company,dc=com +#dc: company +#o: company +#objectclass: top +#objectclass: dcObject +#objectclass: organization + +# Entry 2: cn=admin,dc=company,dc=com +#dn: cn=admin,dc=company,dc=com +#cn: admin +#description: LDAP administrator +#objectclass: simpleSecurityObject +#objectclass: organizationalRole +#userpassword: {SSHA}eUEupkQCTvq9SkrxfWGSe5rX+orrjVbF + +# Entry 3: ou=groups,dc=company,dc=com +dn: ou=groups,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: groups + +# Entry 4: cn=admin,ou=groups,dc=company,dc=com +dn: cn=admin,ou=groups,dc=company,dc=com +cn: admin +gidnumber: 500 +objectclass: posixGroup +objectclass: top + +# Entry 5: cn=users,ou=groups,dc=company,dc=com +dn: cn=users,ou=groups,dc=company,dc=com +cn: users +gidnumber: 501 +objectclass: posixGroup +objectclass: top + +# Entry 6: ou=users,dc=company,dc=com +dn: ou=users,dc=company,dc=com +objectclass: organizationalUnit +objectclass: top +ou: users + +# Entry 7: cn=user1,ou=users,dc=company,dc=com +dn: cn=user1,ou=users,dc=company,dc=com +cn: user1 +gidnumber: 501 +givenname: John1 +homedirectory: /home/users/user1 +objectclass: inetOrgPerson +objectclass: posixAccount +objectclass: top +sn: User1 +uid: user1 +uidnumber: 1001 +userpassword: user1 diff --git a/tests/functional/ldap/docker-compose/clickhouse-service.yml b/tests/functional/ldap/docker-compose/clickhouse-service.yml new file mode 100644 index 00000000000..9787b37abbb --- /dev/null +++ b/tests/functional/ldap/docker-compose/clickhouse-service.yml @@ -0,0 +1,28 @@ +version: '2.3' + +services: + clickhouse: + image: yandex/clickhouse-integration-test + expose: + - "9000" + - "9009" + - "8123" + volumes: + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/config.d:/etc/clickhouse-server/config.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/users.d/:/etc/clickhouse-server/users.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/ssl:/etc/clickhouse-server/ssl" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/config.xml:/etc/clickhouse-server/config.xml" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse/users.xml:/etc/clickhouse-server/users.xml" + - "${CLICKHOUSE_TESTS_SERVER_BIN_PATH:-/usr/bin/clickhouse}:/usr/bin/clickhouse" + - "${CLICKHOUSE_TESTS_ODBC_BRIDGE_BIN_PATH:-/usr/bin/clickhouse-odbc-bridge}:/usr/bin/clickhouse-odbc-bridge" + entrypoint: bash -c "clickhouse server --config-file=/etc/clickhouse-server/config.xml --log-file=/var/log/clickhouse-server/clickhouse-server.log --errorlog-file=/var/log/clickhouse-server/clickhouse-server.err.log" + healthcheck: + test: clickhouse client --query='select 1' + interval: 3s + timeout: 2s + retries: 40 + start_period: 2s + cap_add: + - SYS_PTRACE + security_opt: + - label:disable diff --git a/tests/functional/ldap/docker-compose/docker-compose.yml b/tests/functional/ldap/docker-compose/docker-compose.yml new file mode 100644 index 00000000000..c8ff683df58 --- /dev/null +++ b/tests/functional/ldap/docker-compose/docker-compose.yml @@ -0,0 +1,162 @@ +version: '2.3' + +services: + openldap1: + # plain text + extends: + file: openldap-service.yml + service: openldap + volumes: + - "${CLICKHOUSE_TESTS_DIR}/configs/ldap1/config:/container/service/slapd/assets/config/bootstrap/ldif/custom" + + openldap2: + # TLS - never + extends: + file: openldap-service.yml + service: openldap + environment: + LDAP_TLS: "true" + LDAP_TLS_CRT_FILENAME: "ldap.crt" + LDAP_TLS_KEY_FILENAME: "ldap.key" + LDAP_TLS_DH_PARAM_FILENAME: "dhparam.pem" + LDAP_TLS_CA_CRT_FILENAME: "ca.crt" + LDAP_TLS_ENFORCE: "false" + LDAP_TLS_VERIFY_CLIENT: "never" + volumes: + - "${CLICKHOUSE_TESTS_DIR}/configs/ldap2/config:/container/service/slapd/assets/config/bootstrap/ldif/custom" + - "${CLICKHOUSE_TESTS_DIR}/configs/ldap2/certs:/container/service/slapd/assets/certs/" + + openldap3: + # plain text - custom port + extends: + file: openldap-service.yml + service: openldap + expose: + - "3089" + environment: + LDAP_PORT: "3089" + volumes: + - "${CLICKHOUSE_TESTS_DIR}/configs/ldap3/config:/container/service/slapd/assets/config/bootstrap/ldif/custom" + + openldap4: + # TLS - never custom port + extends: + file: openldap-service.yml + service: openldap + expose: + - "3089" + - "6036" + environment: + LDAP_PORT: "3089" + LDAPS_PORT: "6036" + LDAP_TLS: "true" + LDAP_TLS_CRT_FILENAME: "ldap.crt" + LDAP_TLS_KEY_FILENAME: "ldap.key" + LDAP_TLS_DH_PARAM_FILENAME: "dhparam.pem" + LDAP_TLS_CA_CRT_FILENAME: "ca.crt" + LDAP_TLS_ENFORCE: "false" + LDAP_TLS_VERIFY_CLIENT: "never" + LDAP_TLS_CIPHER_SUITE: "SECURE256:+SECURE128:-VERS-TLS-ALL:+VERS-TLS1.2:-RSA:-DHE-DSS:-CAMELLIA-128-CBC:-CAMELLIA-256-CBC" + volumes: + - "${CLICKHOUSE_TESTS_DIR}/configs/ldap4/config:/container/service/slapd/assets/config/bootstrap/ldif/custom" + - "${CLICKHOUSE_TESTS_DIR}/configs/ldap4/certs:/container/service/slapd/assets/certs/" + + openldap5: + # TLS - try + extends: + file: openldap-service.yml + service: openldap + environment: + LDAP_TLS: "true" + LDAP_TLS_CRT_FILENAME: "ldap.crt" + LDAP_TLS_KEY_FILENAME: "ldap.key" + LDAP_TLS_DH_PARAM_FILENAME: "dhparam.pem" + LDAP_TLS_CA_CRT_FILENAME: "ca.crt" + LDAP_TLS_ENFORCE: "false" + LDAP_TLS_VERIFY_CLIENT: "try" + volumes: + - "${CLICKHOUSE_TESTS_DIR}/configs/ldap5/config:/container/service/slapd/assets/config/bootstrap/ldif/custom" + - "${CLICKHOUSE_TESTS_DIR}/configs/ldap5/certs:/container/service/slapd/assets/certs/" + + phpldapadmin: + extends: + file: openldap-service.yml + service: phpldapadmin + environment: + PHPLDAPADMIN_LDAP_HOSTS: "openldap1" + depends_on: + openldap1: + condition: service_healthy + + zookeeper: + extends: + file: zookeeper-service.yml + service: zookeeper + + clickhouse1: + extends: + file: clickhouse-service.yml + service: clickhouse + hostname: clickhouse1 + volumes: + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse1/database/:/var/lib/clickhouse/" + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse1/logs/:/var/log/clickhouse-server/" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse1/config.d:/etc/clickhouse-server/config.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse1/users.d:/etc/clickhouse-server/users.d" + depends_on: + zookeeper: + condition: service_healthy + + clickhouse2: + extends: + file: clickhouse-service.yml + service: clickhouse + hostname: clickhouse2 + volumes: + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse2/database/:/var/lib/clickhouse/" + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse2/logs/:/var/log/clickhouse-server/" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse2/config.d:/etc/clickhouse-server/config.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse2/users.d:/etc/clickhouse-server/users.d" + depends_on: + zookeeper: + condition: service_healthy + + clickhouse3: + extends: + file: clickhouse-service.yml + service: clickhouse + hostname: clickhouse3 + volumes: + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse3/database/:/var/lib/clickhouse/" + - "${CLICKHOUSE_TESTS_DIR}/_instances/clickhouse3/logs/:/var/log/clickhouse-server/" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse3/config.d:/etc/clickhouse-server/config.d" + - "${CLICKHOUSE_TESTS_DIR}/configs/clickhouse3/users.d:/etc/clickhouse-server/users.d" + depends_on: + zookeeper: + condition: service_healthy + + # dummy service which does nothing, but allows to postpone + # 'docker-compose up -d' till all dependecies will go healthy + all_services_ready: + image: hello-world + depends_on: + clickhouse1: + condition: service_healthy + clickhouse2: + condition: service_healthy + clickhouse3: + condition: service_healthy + zookeeper: + condition: service_healthy + openldap1: + condition: service_healthy + openldap2: + condition: service_healthy + openldap3: + condition: service_healthy + openldap4: + condition: service_healthy + openldap5: + condition: service_healthy + phpldapadmin: + condition: service_healthy diff --git a/tests/functional/ldap/docker-compose/openldap-service.yml b/tests/functional/ldap/docker-compose/openldap-service.yml new file mode 100644 index 00000000000..56690285756 --- /dev/null +++ b/tests/functional/ldap/docker-compose/openldap-service.yml @@ -0,0 +1,40 @@ +version: '2.3' + +services: + openldap: + image: osixia/openldap:1.4.0 + command: "--copy-service --loglevel debug" + environment: + LDAP_ORGANIZATION: "company" + LDAP_DOMAIN: "company.com" + LDAP_ADMIN_PASSWORD: "admin" + LDAP_TLS: "false" + expose: + - "389" + - "636" + healthcheck: + test: echo 1 + interval: 3s + timeout: 2s + retries: 5 + start_period: 2s + security_opt: + - label:disable + + + phpldapadmin: + image: osixia/phpldapadmin:0.9.0 + container_name: phpldapadmin + environment: + PHPLDAPADMIN_HTTPS=false: + ports: + - "8080:80" + healthcheck: + test: echo 1 + interval: 3s + timeout: 2s + retries: 5 + start_period: 2s + security_opt: + - label:disable + diff --git a/tests/functional/ldap/docker-compose/zookeeper-service.yml b/tests/functional/ldap/docker-compose/zookeeper-service.yml new file mode 100644 index 00000000000..f3df33358be --- /dev/null +++ b/tests/functional/ldap/docker-compose/zookeeper-service.yml @@ -0,0 +1,18 @@ +version: '2.3' + +services: + zookeeper: + image: zookeeper:3.4.12 + expose: + - "2181" + environment: + ZOO_TICK_TIME: 500 + ZOO_MY_ID: 1 + healthcheck: + test: echo stat | nc localhost 2181 + interval: 3s + timeout: 2s + retries: 5 + start_period: 2s + security_opt: + - label:disable diff --git a/tests/functional/ldap/regression.py b/tests/functional/ldap/regression.py new file mode 100755 index 00000000000..567807fc0a8 --- /dev/null +++ b/tests/functional/ldap/regression.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import sys +from testflows.core import * + +append_path(sys.path, "..") + +from helpers.cluster import Cluster +from helpers.argparser import argparser +from ldap.requirements import * + +# Cross-outs of known fails +xfails = { + "connection protocols/tls/tls_require_cert='try'": + [(Fail, "can't be tested with self-signed certificates")], + "connection protocols/tls/tls_require_cert='demand'": + [(Fail, "can't be tested with self-signed certificates")], + "connection protocols/starttls/tls_require_cert='try'": + [(Fail, "can't be tested with self-signed certificates")], + "connection protocols/starttls/tls_require_cert='demand'": + [(Fail, "can't be tested with self-signed certificates")], + "connection protocols/tls require cert default demand": + [(Fail, "can't be tested with self-signed certificates")], + "connection protocols/starttls with custom port": + [(Fail, "it seems that starttls is not enabled by default on custom plain-text ports in LDAP server")], + "connection protocols/tls cipher suite": + [(Fail, "can't get it to work")] +} + +@TestFeature +@Name("ldap authentication") +@ArgumentParser(argparser) +@Requirements( + RQ_SRS_007_LDAP_Authentication("1.0") +) +@XFails(xfails) +def regression(self, local, clickhouse_binary_path): + """ClickHouse integration with LDAP regression module. + """ + nodes = { + "clickhouse": ("clickhouse1", "clickhouse2", "clickhouse3"), + } + + with Cluster(local, clickhouse_binary_path, nodes=nodes) as cluster: + self.context.cluster = cluster + + Scenario(run=load("ldap.tests.sanity", "scenario")) + Scenario(run=load("ldap.tests.multiple_servers", "scenario")) + Feature(run=load("ldap.tests.connections", "feature")) + Feature(run=load("ldap.tests.server_config", "feature")) + Feature(run=load("ldap.tests.user_config", "feature")) + Feature(run=load("ldap.tests.authentications", "feature")) + +if main(): + regression() diff --git a/tests/functional/ldap/requirements/__init__.py b/tests/functional/ldap/requirements/__init__.py new file mode 100644 index 00000000000..02f7d430154 --- /dev/null +++ b/tests/functional/ldap/requirements/__init__.py @@ -0,0 +1 @@ +from .requirements import * diff --git a/tests/functional/ldap/requirements/requirements.py b/tests/functional/ldap/requirements/requirements.py new file mode 100644 index 00000000000..92491f4318b --- /dev/null +++ b/tests/functional/ldap/requirements/requirements.py @@ -0,0 +1,928 @@ +# These requirements were auto generated +# from software requirements specification (SRS) +# document by TestFlows v1.6.200623.1103543. +# Do not edit by hand but re-generate instead +# using 'tfs requirements generate' command. +from testflows.core import Requirement + +RQ_SRS_007_LDAP_Authentication = Requirement( + name='RQ.SRS-007.LDAP.Authentication', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support user authentication via an [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_MultipleServers = Requirement( + name='RQ.SRS-007.LDAP.Authentication.MultipleServers', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying multiple [LDAP] servers that can be used to authenticate\n' + 'users.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Protocol_PlainText = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Protocol.PlainText', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support user authentication using plain text `ldap://` non secure protocol.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Protocol_TLS = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Protocol.TLS', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support user authentication using `SSL/TLS` `ldaps://` secure protocol.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Protocol_StartTLS = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Protocol.StartTLS', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support user authentication using legacy `StartTLS` protocol which is a\n' + 'plain text `ldap://` protocol that is upgraded to [TLS].\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_TLS_Certificate_Validation = Requirement( + name='RQ.SRS-007.LDAP.Authentication.TLS.Certificate.Validation', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support certificate validation used for [TLS] connections.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_TLS_Certificate_SelfSigned = Requirement( + name='RQ.SRS-007.LDAP.Authentication.TLS.Certificate.SelfSigned', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support self-signed certificates for [TLS] connections.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_TLS_Certificate_SpecificCertificationAuthority = Requirement( + name='RQ.SRS-007.LDAP.Authentication.TLS.Certificate.SpecificCertificationAuthority', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support certificates signed by specific Certification Authority for [TLS] connections.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Server_Configuration_Invalid = Requirement( + name='RQ.SRS-007.LDAP.Server.Configuration.Invalid', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL return an error and prohibit user login if [LDAP] server configuration is not valid.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_User_Configuration_Invalid = Requirement( + name='RQ.SRS-007.LDAP.User.Configuration.Invalid', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL return an error and prohibit user login if user configuration is not valid.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Mechanism_Anonymous = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Mechanism.Anonymous', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL return an error and prohibit authentication using [Anonymous Authentication Mechanism of Simple Bind]\n' + 'authentication mechanism.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Mechanism_Unauthenticated = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Mechanism.Unauthenticated', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL return an error and prohibit authentication using [Unauthenticated Authentication Mechanism of Simple Bind]\n' + 'authentication mechanism.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Mechanism_NamePassword = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Mechanism.NamePassword', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL allow authentication using only [Name/Password Authentication Mechanism of Simple Bind]\n' + 'authentication mechanism.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Valid = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Valid', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL only allow user authentication using [LDAP] server if and only if\n' + 'user name and password match [LDAP] server records for the user.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Invalid = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Invalid', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL return an error and prohibit authentication if either user name or password\n' + 'do not match [LDAP] server records for the user.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Invalid_DeletedUser = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Invalid.DeletedUser', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL return an error and prohibit authentication if the user\n' + 'has been deleted from the [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_UsernameChanged = Requirement( + name='RQ.SRS-007.LDAP.Authentication.UsernameChanged', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL return an error and prohibit authentication if the username is changed\n' + 'on the [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_PasswordChanged = Requirement( + name='RQ.SRS-007.LDAP.Authentication.PasswordChanged', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL return an error and prohibit authentication if the password \n' + 'for the user is changed on the [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_LDAPServerRestart = Requirement( + name='RQ.SRS-007.LDAP.Authentication.LDAPServerRestart', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support authenticating users after [LDAP] server is restarted.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_ClickHouseServerRestart = Requirement( + name='RQ.SRS-007.LDAP.Authentication.ClickHouseServerRestart', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support authenticating users after server is restarted.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Parallel = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Parallel', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support parallel authentication of users using [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Parallel_ValidAndInvalid = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Parallel.ValidAndInvalid', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support authentication of valid users and \n' + 'prohibit authentication of invalid users using [LDAP] server \n' + 'in parallel without having invalid attempts affecting valid authentications.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_UnreachableServer = Requirement( + name='RQ.SRS-007.LDAP.UnreachableServer', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL return an error and prohibit user login if [LDAP] server is unreachable.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_Name = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.Name', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL not support empty string as a server name.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_Host = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.Host', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` parameter to specify [LDAP]\n' + 'server hostname or IP, this parameter SHALL be mandatory and SHALL not be empty. \n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_Port = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.Port', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` parameter to specify [LDAP] server port.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_Port_Default = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.Port.Default', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL use default port number `636` if `enable_tls` is set to `yes` or `389` otherwise.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_AuthDN_Prefix = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.AuthDN.Prefix', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` parameter to specify the prefix\n' + 'of value used to construct the DN to bound to during authentication via [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_AuthDN_Suffix = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.AuthDN.Suffix', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` parameter to specify the suffix \n' + 'of value used to construct the DN to bound to during authentication via [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_AuthDN_Value = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.AuthDN.Value', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL construct DN as `auth_dn_prefix + escape(user_name) + auth_dn_suffix` string.\n' + '\n' + "> This implies that auth_dn_suffix should usually have comma ',' as its first non-space character.\n" + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_EnableTLS = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.EnableTLS', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` parameter to trigger the use of secure connection to the [LDAP] server. \n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_Default = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.EnableTLS.Options.Default', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL use `yes` value as the default for `` parameter\n' + 'to enable SSL/TLS `ldaps://` protocol. \n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_No = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.EnableTLS.Options.No', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `no` as the value of `` parameter to enable \n' + 'plain text `ldap://` protocol.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_Yes = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.EnableTLS.Options.Yes', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `yes` as the value of `` parameter to enable \n' + 'SSL/TLS `ldaps://` protocol.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_StartTLS = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.EnableTLS.Options.StartTLS', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `starttls` as the value of `` parameter to enable \n' + 'legacy `StartTLS` protocol that used plain text `ldap://` protocol, upgraded to [TLS].\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSMinimumProtocolVersion = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSMinimumProtocolVersion', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` parameter to specify \n' + 'the minimum protocol version of SSL/TLS.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSMinimumProtocolVersion_Values = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSMinimumProtocolVersion.Values', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `ssl2`, `ssl3`, `tls1.0`, `tls1.1`, and `tls1.2`\n' + 'as a value of the `` parameter.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSMinimumProtocolVersion_Default = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSMinimumProtocolVersion.Default', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL set `tls1.2` as the default value of the `` parameter. \n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSRequireCert', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` parameter to specify [TLS] peer \n' + 'certificate verification behavior.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Default = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSRequireCert.Options.Default', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL use `demand` value as the default for the `` parameter.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Demand = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSRequireCert.Options.Demand', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `demand` as the value of `` parameter to\n' + 'enable requesting of client certificate. If no certificate is provided, or a bad certificate is\n' + 'provided, the session SHALL be immediately terminated.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Allow = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSRequireCert.Options.Allow', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `allow` as the value of `` parameter to\n' + 'enable requesting of client certificate. If no\n' + 'certificate is provided, the session SHALL proceed normally. \n' + 'If a bad certificate is provided, it SHALL be ignored and the session SHALL proceed normally.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Try = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSRequireCert.Options.Try', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `try` as the value of `` parameter to\n' + 'enable requesting of client certificate. If no certificate is provided, the session\n' + 'SHALL proceed normally. If a bad certificate is provided, the session SHALL be \n' + 'immediately terminated.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Never = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSRequireCert.Options.Never', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying `never` as the value of `` parameter to\n' + 'disable requesting of client certificate.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSCertFile = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSCertFile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` to specify the path to certificate file used by\n' + '[ClickHouse] to establish connection with the [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSKeyFile = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSKeyFile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` to specify the path to key file for the certificate\n' + 'specified by the `` parameter.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSCACertDir = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSCACertDir', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` parameter to specify to a path to \n' + 'the directory containing [CA] certificates used to verify certificates provided by the [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSCACertFile = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSCACertFile', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `` parameter to specify a path to a specific \n' + '[CA] certificate file used to verify certificates provided by the [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_TLSCipherSuite = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.TLSCipherSuite', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support `tls_cipher_suite` parameter to specify allowed cipher suites.\n' + 'The value SHALL use the same format as the `ciphersuites` in the [OpenSSL Ciphers].\n' + '\n' + 'For example, \n' + '\n' + '```xml\n' + 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:AES256-GCM-SHA384\n' + '```\n' + '\n' + 'The available suites SHALL depend on the [OpenSSL] library version and variant used to build\n' + '[ClickHouse] and therefore might change.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_Server_Syntax = Requirement( + name='RQ.SRS-007.LDAP.Configuration.Server.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following example syntax to create an entry for an [LDAP] server inside the `config.xml`\n' + 'configuration file or of any configuration file inside the `config.d` directory.\n' + '\n' + '```xml\n' + '\n' + ' \n' + ' localhost\n' + ' 636\n' + ' cn=\n' + ' , ou=users, dc=example, dc=com\n' + ' yes\n' + ' tls1.2\n' + ' demand\n' + ' /path/to/tls_cert_file\n' + ' /path/to/tls_key_file\n' + ' /path/to/tls_ca_cert_file\n' + ' /path/to/tls_ca_cert_dir\n' + ' ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:AES256-GCM-SHA384\n' + ' \n' + '\n' + '```\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_User_Syntax = Requirement( + name='RQ.SRS-007.LDAP.Configuration.User.Syntax', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support the following example syntax to create a user that is authenticated using\n' + 'an [LDAP] server inside the `users.xml` file or any configuration file inside the `users.d` directory.\n' + '\n' + '```xml\n' + '\n' + ' \n' + ' \n' + ' \n' + ' my_ldap_server\n' + ' \n' + ' \n' + ' \n' + '\n' + '```\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_User_Name_Empty = Requirement( + name='RQ.SRS-007.LDAP.Configuration.User.Name.Empty', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL not support empty string as a user name.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_User_BothPasswordAndLDAP = Requirement( + name='RQ.SRS-007.LDAP.Configuration.User.BothPasswordAndLDAP', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL throw an error if `` is specified for the user and at the same \n' + 'time user configuration contains any of the `` entries.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_User_LDAP_InvalidServerName_NotDefined = Requirement( + name='RQ.SRS-007.LDAP.Configuration.User.LDAP.InvalidServerName.NotDefined', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL throw an error during any authentification attempt\n' + 'if the name of the [LDAP] server used inside the `` entry \n' + 'is not defined in the `` section. \n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_User_LDAP_InvalidServerName_Empty = Requirement( + name='RQ.SRS-007.LDAP.Configuration.User.LDAP.InvalidServerName.Empty', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL throw an error during any authentification attempt\n' + 'if the name of the [LDAP] server used inside the `` entry\n' + 'is empty. \n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_User_OnlyOneServer = Requirement( + name='RQ.SRS-007.LDAP.Configuration.User.OnlyOneServer', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support specifying only one [LDAP] server for a given user.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_User_Name_Long = Requirement( + name='RQ.SRS-007.LDAP.Configuration.User.Name.Long', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support long user names of at least 256 bytes\n' + 'to specify users that can be authenticated using an [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Configuration_User_Name_UTF8 = Requirement( + name='RQ.SRS-007.LDAP.Configuration.User.Name.UTF8', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support user names that contain [UTF-8] characters.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Username_Empty = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Username.Empty', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL not support authenticating users with empty username.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Username_Long = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Username.Long', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support authenticating users with a long username of at least 256 bytes.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Username_UTF8 = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Username.UTF8', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support authentication users with a username that contains [UTF-8] characters.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Password_Empty = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Password.Empty', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL not support authenticating users with empty passwords\n' + 'even if an empty password is valid for the user and\n' + 'is allowed by the [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Password_Long = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Password.Long', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support long password of at least 256 bytes\n' + 'that can be used to authenticate users using an [LDAP] server.\n' + ), + link=None + ) + +RQ_SRS_007_LDAP_Authentication_Password_UTF8 = Requirement( + name='RQ.SRS-007.LDAP.Authentication.Password.UTF8', + version='1.0', + priority=None, + group=None, + type=None, + uid=None, + description=( + '[ClickHouse] SHALL support [UTF-8] characters in passwords\n' + 'used to authenticate users using an [LDAP] server.\n' + ), + link=None + ) diff --git a/tests/functional/ldap/tests/authentications.py b/tests/functional/ldap/tests/authentications.py new file mode 100644 index 00000000000..ca152fb0409 --- /dev/null +++ b/tests/functional/ldap/tests/authentications.py @@ -0,0 +1,460 @@ +# -*- coding: utf-8 -*- +import random + +from multiprocessing.dummy import Pool +from testflows.core import * +from testflows.asserts import error +from ldap.tests.common import * +from ldap.requirements import * + +servers = { + "openldap1": { + "host": "openldap1", + "port": "389", + "enable_tls": "no", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }, + "openldap2": { + "host": "openldap2", + "port": "636", + "enable_tls": "yes", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com", + "tls_require_cert": "never", + } +} + +@TestStep(When) +@Name("I login as {username} and execute query") +def login_and_execute_query(self, username, password, exitcode=None, message=None, steps=True): + self.context.node.query("SELECT 1", + settings=[("user", username), ("password", password)], + exitcode=exitcode or 0, + message=message, steps=steps) + +@TestScenario +def add_user_to_ldap_and_login(self, server, user=None, ch_user=None, login=None, exitcode=None, message=None): + """Add user to LDAP and ClickHouse and then try to login.""" + self.context.ldap_node = self.context.cluster.node(server) + + if ch_user is None: + ch_user = {} + if login is None: + login = {} + if user is None: + user = {"cn": "myuser", "userpassword": "myuser"} + + with ldap_user(**user) as user: + ch_user["username"] = ch_user.get("username", user["cn"]) + ch_user["server"] = ch_user.get("server", user["_server"]) + + with ldap_authenticated_users(ch_user, config_file=f"ldap_users_{getuid()}.xml", restart=True): + username = login.get("username", user["cn"]) + password = login.get("password", user["userpassword"]) + login_and_execute_query(username=username, password=password, exitcode=exitcode, message=message) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Parallel("1.0"), + RQ_SRS_007_LDAP_Authentication_Parallel_ValidAndInvalid("1.0") +) +def parallel_login(self, server, user_count=10, timeout=200): + """Check that login of valid and invalid LDAP authenticated users works in parallel.""" + self.context.ldap_node = self.context.cluster.node(server) + user = None + + users = [{"cn": f"parallel_user{i}", "userpassword": randomword(20)} for i in range(user_count)] + + with ldap_users(*users): + with ldap_authenticated_users(*[{"username": user["cn"], "server": server} for user in users]): + + def login_with_valid_username_and_password(users, i, iterations=10): + with When(f"valid users try to login #{i}"): + for i in range(iterations): + random_user = users[random.randint(0, len(users)-1)] + login_and_execute_query(username=random_user["cn"], password=random_user["userpassword"], steps=False) + + def login_with_valid_username_and_invalid_password(users, i, iterations=10): + with When(f"users try to login with valid username and invalid password #{i}"): + for i in range(iterations): + random_user = users[random.randint(0, len(users)-1)] + login_and_execute_query(username=random_user["cn"], + password=(random_user["userpassword"] + randomword(1)), + exitcode=4, + message=f"DB::Exception: {random_user['cn']}: Authentication failed: password is incorrect or there is no user with such name", + steps=False) + + def login_with_invalid_username_and_valid_password(users, i, iterations=10): + with When(f"users try to login with invalid username and valid password #{i}"): + for i in range(iterations): + random_user = dict(users[random.randint(0, len(users)-1)]) + random_user["cn"] += randomword(1) + login_and_execute_query(username=random_user["cn"], + password=random_user["userpassword"], + exitcode=4, + message=f"DB::Exception: {random_user['cn']}: Authentication failed: password is incorrect or there is no user with such name", + steps=False) + + with When("I login in parallel"): + p = Pool(15) + tasks = [] + for i in range(5): + tasks.append(p.apply_async(login_with_valid_username_and_password, (users, i, 50,))) + tasks.append(p.apply_async(login_with_valid_username_and_invalid_password, (users, i, 50,))) + tasks.append(p.apply_async(login_with_invalid_username_and_valid_password, (users, i, 50,))) + + with Then("it should work"): + for task in tasks: + task.get(timeout=timeout) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0"), + RQ_SRS_007_LDAP_Authentication_Invalid_DeletedUser("1.0") +) +def login_after_user_is_deleted_from_ldap(self, server): + """Check that login fails after user is deleted from LDAP.""" + self.context.ldap_node = self.context.cluster.node(server) + user = None + + try: + with Given(f"I add user to LDAP"): + user = {"cn": "myuser", "userpassword": "myuser"} + user = add_user_to_ldap(**user) + + with ldap_authenticated_users({"username": user["cn"], "server": server}, config_file=f"ldap_users_{getuid()}.xml", restart=True): + login_and_execute_query(username=user["cn"], password=user["userpassword"]) + + with When("I delete this user from LDAP"): + delete_user_from_ldap(user) + + with Then("when I try to login again it should fail"): + login_and_execute_query(username=user["cn"], password=user["userpassword"], + exitcode=4, + message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name" + ) + finally: + with Finally("I make sure LDAP user is deleted"): + if user is not None: + delete_user_from_ldap(user, exitcode=None) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0"), + RQ_SRS_007_LDAP_Authentication_PasswordChanged("1.0") +) +def login_after_user_password_changed_in_ldap(self, server): + """Check that login fails after user password is changed in LDAP.""" + self.context.ldap_node = self.context.cluster.node(server) + user = None + + try: + with Given(f"I add user to LDAP"): + user = {"cn": "myuser", "userpassword": "myuser"} + user = add_user_to_ldap(**user) + + with ldap_authenticated_users({"username": user["cn"], "server": server}, config_file=f"ldap_users_{getuid()}.xml", restart=True): + login_and_execute_query(username=user["cn"], password=user["userpassword"]) + + with When("I change user password in LDAP"): + change_user_password_in_ldap(user, "newpassword") + + with Then("when I try to login again it should fail"): + login_and_execute_query(username=user["cn"], password=user["userpassword"], + exitcode=4, + message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name" + ) + finally: + with Finally("I make sure LDAP user is deleted"): + if user is not None: + delete_user_from_ldap(user, exitcode=None) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0"), + RQ_SRS_007_LDAP_Authentication_UsernameChanged("1.0") +) +def login_after_user_cn_changed_in_ldap(self, server): + """Check that login fails after user cn is changed in LDAP.""" + self.context.ldap_node = self.context.cluster.node(server) + user = None + + try: + with Given(f"I add user to LDAP"): + user = {"cn": "myuser", "userpassword": "myuser"} + user = add_user_to_ldap(**user) + + with ldap_authenticated_users({"username": user["cn"], "server": server}, config_file=f"ldap_users_{getuid()}.xml", restart=True): + login_and_execute_query(username=user["cn"], password=user["userpassword"]) + + with When("I change user password in LDAP"): + change_user_cn_in_ldap(user, "myuser2") + + with Then("when I try to login again it should fail"): + login_and_execute_query(username=user["cn"], password=user["userpassword"], + exitcode=4, + message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name" + ) + finally: + with Finally("I make sure LDAP user is deleted"): + if user is not None: + delete_user_from_ldap(user, exitcode=None) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Valid("1.0"), + RQ_SRS_007_LDAP_Authentication_LDAPServerRestart("1.0") +) +def login_after_ldap_server_is_restarted(self, server, timeout=60): + """Check that login succeeds after LDAP server is restarted.""" + self.context.ldap_node = self.context.cluster.node(server) + user = None + + try: + with Given(f"I add user to LDAP"): + user = {"cn": "myuser", "userpassword": getuid()} + user = add_user_to_ldap(**user) + + with ldap_authenticated_users({"username": user["cn"], "server": server}): + login_and_execute_query(username=user["cn"], password=user["userpassword"]) + + with When("I restart LDAP server"): + self.context.ldap_node.restart() + + with Then("I try to login until it works", description=f"timeout {timeout} sec"): + started = time.time() + while True: + r = self.context.node.query("SELECT 1", + settings=[("user", user["cn"]), ("password", user["userpassword"])], + no_checks=True) + if r.exitcode == 0: + break + assert time.time() - started < timeout, error(r.output) + finally: + with Finally("I make sure LDAP user is deleted"): + if user is not None: + delete_user_from_ldap(user, exitcode=None) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Valid("1.0"), + RQ_SRS_007_LDAP_Authentication_ClickHouseServerRestart("1.0") +) +def login_after_clickhouse_server_is_restarted(self, server, timeout=60): + """Check that login succeeds after ClickHouse server is restarted.""" + self.context.ldap_node = self.context.cluster.node(server) + user = None + + try: + with Given(f"I add user to LDAP"): + user = {"cn": "myuser", "userpassword": getuid()} + user = add_user_to_ldap(**user) + + with ldap_authenticated_users({"username": user["cn"], "server": server}): + login_and_execute_query(username=user["cn"], password=user["userpassword"]) + + with When("I restart ClickHouse server"): + self.context.node.restart() + + with Then("I try to login until it works", description=f"timeout {timeout} sec"): + started = time.time() + while True: + r = self.context.node.query("SELECT 1", + settings=[("user", user["cn"]), ("password", user["userpassword"])], + no_checks=True) + if r.exitcode == 0: + break + assert time.time() - started < timeout, error(r.output) + finally: + with Finally("I make sure LDAP user is deleted"): + if user is not None: + delete_user_from_ldap(user, exitcode=None) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0"), + RQ_SRS_007_LDAP_Authentication_Password_Empty("1.0") +) +def valid_username_with_valid_empty_password(self, server): + """Check that we can't login using valid username that has empty password.""" + user = {"cn": "empty_password", "userpassword": ""} + exitcode = 4 + message = f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name" + + add_user_to_ldap_and_login(user=user, exitcode=exitcode, message=message, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0"), + RQ_SRS_007_LDAP_Authentication_Password_Empty("1.0") +) +def valid_username_and_invalid_empty_password(self, server): + """Check that we can't login using valid username but invalid empty password.""" + username = "user_non_empty_password" + user = {"cn": username, "userpassword": username} + login = {"password": ""} + + exitcode = 4 + message = f"DB::Exception: {username}: Authentication failed: password is incorrect or there is no user with such name" + + add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Valid("1.0") +) +def valid_username_and_password(self, server): + """Check that we can login using valid username and password.""" + username = "valid_username_and_password" + user = {"cn": username, "userpassword": username} + + with When(f"I add user {username} to LDAP and try to login"): + add_user_to_ldap_and_login(user=user, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0") +) +def valid_username_and_password_invalid_server(self, server=None): + """Check that we can't login using valid username and valid + password but for a different server.""" + self.context.ldap_node = self.context.cluster.node("openldap1") + + user = {"username": "user2", "userpassword": "user2", "server": "openldap1"} + + exitcode = 4 + message = f"DB::Exception: user2: Authentication failed: password is incorrect or there is no user with such name" + + with ldap_authenticated_users(user, config_file=f"ldap_users_{getuid()}.xml", restart=True): + login_and_execute_query(username="user2", password="user2", exitcode=exitcode, message=message) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Valid("1.0"), + RQ_SRS_007_LDAP_Authentication_Username_Long("1.0"), + RQ_SRS_007_LDAP_Configuration_User_Name_Long("1.0") +) +def valid_long_username_and_short_password(self, server): + """Check that we can login using valid very long username and short password.""" + username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890" + user = {"cn": username, "userpassword": "long_username"} + + add_user_to_ldap_and_login(user=user, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0") +) +def invalid_long_username_and_valid_short_password(self, server): + """Check that we can't login using slightly invalid long username but valid password.""" + username = "long_username_12345678901234567890123456789012345678901234567890123456789012345678901234567890" + user = {"cn": username, "userpassword": "long_username"} + login = {"username": f"{username}?"} + + exitcode = 4 + message=f"DB::Exception: {login['username']}: Authentication failed: password is incorrect or there is no user with such name" + + add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Valid("1.0"), + RQ_SRS_007_LDAP_Authentication_Password_Long("1.0") +) +def valid_short_username_and_long_password(self, server): + """Check that we can login using valid short username with very long password.""" + username = "long_password" + user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"} + add_user_to_ldap_and_login(user=user, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0") +) +def valid_short_username_and_invalid_long_password(self, server): + """Check that we can't login using valid short username and invalid long password.""" + username = "long_password" + user = {"cn": username, "userpassword": "long_password_12345678901234567890123456789012345678901234567890123456789012345678901234567890"} + login = {"password": user["userpassword"] + "1"} + + exitcode = 4 + message=f"DB::Exception: {username}: Authentication failed: password is incorrect or there is no user with such name" + + add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0") +) +def valid_username_and_invalid_password(self, server): + """Check that we can't login using valid username and invalid password.""" + username = "valid_username_and_invalid_password" + user = {"cn": username, "userpassword": username} + login = {"password": user["userpassword"] + "1"} + + exitcode = 4 + message=f"DB::Exception: {username}: Authentication failed: password is incorrect or there is no user with such name" + + add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Invalid("1.0") +) +def invalid_username_and_valid_password(self, server): + """Check that we can't login using slightly invalid username but valid password.""" + username = "invalid_username_and_valid_password" + user = {"cn": username, "userpassword": username} + login = {"username": user["cn"] + "1"} + + exitcode = 4 + message=f"DB::Exception: {login['username']}: Authentication failed: password is incorrect or there is no user with such name" + + add_user_to_ldap_and_login(user=user, login=login, exitcode=exitcode, message=message, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Valid("1.0"), + RQ_SRS_007_LDAP_Authentication_Username_UTF8("1.0"), + RQ_SRS_007_LDAP_Configuration_User_Name_UTF8("1.0") +) +def valid_utf8_username_and_ascii_password(self, server): + """Check that we can login using valid utf-8 username with ascii password.""" + username = "utf8_username_Gãńdåłf_Thê_Gręât" + user = {"cn": username, "userpassword": "utf8_username"} + + add_user_to_ldap_and_login(user=user, server=server) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Valid("1.0"), + RQ_SRS_007_LDAP_Authentication_Password_UTF8("1.0") +) +def valid_ascii_username_and_utf8_password(self, server): + """Check that we can login using valid ascii username with utf-8 password.""" + username = "utf8_password" + user = {"cn": username, "userpassword": "utf8_password_Gãńdåłf_Thê_Gręât"} + + add_user_to_ldap_and_login(user=user, server=server) + +@TestScenario +def empty_username_and_empty_password(self, server=None): + """Check that we can login using empty username and empty password as + it will use the default user and that has an empty password.""" + login_and_execute_query(username="", password="") + +@TestFeature +@Name("user authentications") +@Requirements( + RQ_SRS_007_LDAP_Authentication_Mechanism_NamePassword("1.0") +) +def feature(self, servers=None, node="clickhouse1"): + self.context.node = self.context.cluster.node(node) + + if servers is None: + servers = globals()["servers"] + + with ldap_servers(servers): + for scenario in loads(current_module(), Scenario): + scenario(server="openldap1") diff --git a/tests/functional/ldap/tests/common.py b/tests/functional/ldap/tests/common.py new file mode 100644 index 00000000000..e0897cb6e9f --- /dev/null +++ b/tests/functional/ldap/tests/common.py @@ -0,0 +1,354 @@ +import os +import uuid +import time +import string +import random +import textwrap +import xml.etree.ElementTree as xmltree + +from collections import namedtuple +from contextlib import contextmanager + +import testflows.settings as settings + +from testflows.core import * +from testflows.asserts import error + +def getuid(): + return str(uuid.uuid1()).replace('-', '_') + +xml_with_utf8 = '\n' + +def xml_indent(elem, level=0, by=" "): + i = "\n" + level * by + if len(elem): + if not elem.text or not elem.text.strip(): + elem.text = i + by + if not elem.tail or not elem.tail.strip(): + elem.tail = i + for elem in elem: + xml_indent(elem, level + 1) + if not elem.tail or not elem.tail.strip(): + elem.tail = i + else: + if level and (not elem.tail or not elem.tail.strip()): + elem.tail = i + +def xml_append(root, tag, text): + element = xmltree.Element(tag) + element.text = text + root.append(element) + return element + +Config = namedtuple("Config", "content path name uid preprocessed_name") + +ASCII_CHARS = string.ascii_lowercase + string.ascii_uppercase + string.digits + +def randomword(length, chars=ASCII_CHARS): + return ''.join(random.choice(chars) for i in range(length)) + +def add_config(config, timeout=20, restart=False): + """Add dynamic configuration file to ClickHouse. + + :param node: node + :param config: configuration file description + :param timeout: timeout, default: 20 sec + """ + node = current().context.node + try: + with Given(f"{config.name}"): + if settings.debug: + with When("I output the content of the config"): + debug(config.content) + + with When("I add the config", description=config.path): + command = f"cat < {config.path}\n{config.content}\nHEREDOC" + node.command(command, steps=False, exitcode=0) + + with Then(f"{config.preprocessed_name} should be updated", description=f"timeout {timeout}"): + started = time.time() + command = f"cat /var/lib/clickhouse/preprocessed_configs/{config.preprocessed_name} | grep {config.uid}{' > /dev/null' if not settings.debug else ''}" + while time.time() - started < timeout: + exitcode = node.command(command, steps=False).exitcode + if exitcode == 0: + break + time.sleep(1) + assert exitcode == 0, error() + + if restart: + with When("I restart ClickHouse to apply the config changes"): + node.restart(safe=False) + yield + finally: + with Finally(f"I remove {config.name}"): + with By("removing the config file", description=config.path): + node.command(f"rm -rf {config.path}", exitcode=0) + + with Then(f"{config.preprocessed_name} should be updated"): + started = time.time() + command = f"cat /var/lib/clickhouse/preprocessed_configs/{config.preprocessed_name} | grep '{config.uid}'{' > /dev/null' if not settings.debug else ''}" + while time.time() - started < timeout: + exitcode = node.command(command, steps=False).exitcode + if exitcode == 1: + break + time.sleep(1) + assert exitcode == 1, error() + +def create_ldap_servers_config_content(servers, config_d_dir="/etc/clickhouse-server/config.d", config_file="ldap_servers.xml"): + """Create LDAP servers configuration content. + """ + uid = getuid() + path = os.path.join(config_d_dir, config_file) + name = config_file + + root = xmltree.fromstring("") + xml_servers = root.find("ldap_servers") + xml_servers.append(xmltree.Comment(text=f"LDAP servers {uid}")) + + for _name, server in servers.items(): + xml_server = xmltree.Element(_name) + for key, value in server.items(): + xml_append(xml_server, key, value) + xml_servers.append(xml_server) + + xml_indent(root) + content = xml_with_utf8 + str(xmltree.tostring(root, short_empty_elements=False, encoding="utf-8"), "utf-8") + + return Config(content, path, name, uid, "config.xml") + +@contextmanager +def ldap_servers(servers, config_d_dir="/etc/clickhouse-server/config.d", config_file="ldap_servers.xml", + timeout=20, restart=False): + """Add LDAP servers configuration. + """ + config = create_ldap_servers_config_content(servers, config_d_dir, config_file) + return add_config(config, restart=restart) + +def create_ldap_users_config_content(*users, config_d_dir="/etc/clickhouse-server/users.d", config_file="ldap_users.xml"): + """Create LDAP users configuration file content. + """ + uid = getuid() + path = os.path.join(config_d_dir, config_file) + name = config_file + + root = xmltree.fromstring("") + xml_users = root.find("users") + xml_users.append(xmltree.Comment(text=f"LDAP users {uid}")) + + for user in users: + xml_user = xmltree.Element(user['username']) + xml_user_server = xmltree.Element("ldap") + xml_append(xml_user_server, "server", user["server"]) + xml_user.append(xml_user_server) + xml_users.append(xml_user) + + xml_indent(root) + content = xml_with_utf8 + str(xmltree.tostring(root, short_empty_elements=False, encoding="utf-8"), "utf-8") + + return Config(content, path, name, uid, "users.xml") + +@contextmanager +def ldap_authenticated_users(*users, config_d_dir="/etc/clickhouse-server/users.d", + config_file=None, timeout=20, restart=True, config=None): + """Add LDAP authenticated user configuration. + """ + if config_file is None: + config_file = f"ldap_users_{getuid()}.xml" + if config is None: + config = create_ldap_users_config_content(*users, config_d_dir=config_d_dir, config_file=config_file) + return add_config(config, restart=restart) + +def invalid_server_config(servers, message=None, tail=13, timeout=20): + """Check that ClickHouse errors when trying to load invalid LDAP servers configuration file. + """ + node = current().context.node + if message is None: + message = "Exception: Failed to merge config with '/etc/clickhouse-server/config.d/ldap_servers.xml'" + + config = create_ldap_servers_config_content(servers) + try: + node.command("echo -e \"%s\" > /var/log/clickhouse-server/clickhouse-server.err.log" % ("-\\n" * tail)) + + with When("I add the config", description=config.path): + command = f"cat < {config.path}\n{config.content}\nHEREDOC" + node.command(command, steps=False, exitcode=0) + + with Then("server shall fail to merge the new config"): + started = time.time() + command = f"tail -n {tail} /var/log/clickhouse-server/clickhouse-server.err.log | grep \"{message}\"" + while time.time() - started < timeout: + exitcode = node.command(command, steps=False).exitcode + if exitcode == 0: + break + time.sleep(1) + assert exitcode == 0, error() + finally: + with Finally(f"I remove {config.name}"): + with By("removing the config file", description=config.path): + node.command(f"rm -rf {config.path}", exitcode=0) + +def invalid_user_config(servers, config, message=None, tail=13, timeout=20): + """Check that ClickHouse errors when trying to load invalid LDAP users configuration file. + """ + node = current().context.node + if message is None: + message = "Exception: Failed to merge config with '/etc/clickhouse-server/users.d/ldap_users.xml'" + + with ldap_servers(servers): + try: + node.command("echo -e \"%s\" > /var/log/clickhouse-server/clickhouse-server.err.log" % ("\\n" * tail)) + with When("I add the config", description=config.path): + command = f"cat < {config.path}\n{config.content}\nHEREDOC" + node.command(command, steps=False, exitcode=0) + + with Then("server shall fail to merge the new config"): + started = time.time() + command = f"tail -n {tail} /var/log/clickhouse-server/clickhouse-server.err.log | grep \"{message}\"" + while time.time() - started < timeout: + exitcode = node.command(command, steps=False).exitcode + if exitcode == 0: + break + time.sleep(1) + assert exitcode == 0, error() + finally: + with Finally(f"I remove {config.name}"): + with By("removing the config file", description=config.path): + node.command(f"rm -rf {config.path}", exitcode=0) + +def add_user_to_ldap(cn, userpassword, givenname=None, homedirectory=None, sn=None, uid=None, uidnumber=None, node=None): + """Add user entry to LDAP.""" + if node is None: + node = current().context.ldap_node + if uid is None: + uid = cn + if givenname is None: + givenname = "John" + if homedirectory is None: + homedirectory = "/home/users" + if sn is None: + sn = "User" + if uidnumber is None: + uidnumber = 2000 + + user = { + "dn": f"cn={cn},ou=users,dc=company,dc=com", + "cn": cn, + "gidnumber": 501, + "givenname": givenname, + "homedirectory": homedirectory, + "objectclass": ["inetOrgPerson", "posixAccount", "top"], + "sn": sn, + "uid": uid, + "uidnumber": uidnumber, + "userpassword": userpassword, + "_server": node.name + } + + lines = [] + for key, value in user.items(): + if key.startswith("_"): + continue + elif key == "objectclass": + for cls in value: + lines.append(f"objectclass: {cls}") + else: + lines.append(f"{key}: {value}") + + ldif = "\n".join(lines) + + r = node.command( + f"echo -e \"{ldif}\" | ldapadd -x -H ldap://localhost -D \"cn=admin,dc=company,dc=com\" -w admin") + assert r.exitcode == 0, error() + + return user + +def delete_user_from_ldap(user, node=None, exitcode=0): + """Delete user entry from LDAP.""" + if node is None: + node = current().context.ldap_node + r = node.command( + f"ldapdelete -x -H ldap://localhost -D \"cn=admin,dc=company,dc=com\" -w admin \"{user['dn']}\"") + if exitcode is not None: + assert r.exitcode == exitcode, error() + +def change_user_password_in_ldap(user, new_password, node=None, exitcode=0): + """Change user password in LDAP.""" + if node is None: + node = current().context.ldap_node + + ldif = (f"dn: {user['dn']}\n" + "changetype: modify\n" + "replace: userpassword\n" + f"userpassword: {new_password}") + + r = node.command( + f"echo -e \"{ldif}\" | ldapmodify -x -H ldap://localhost -D \"cn=admin,dc=company,dc=com\" -w admin") + + if exitcode is not None: + assert r.exitcode == exitcode, error() + +def change_user_cn_in_ldap(user, new_cn, node=None, exitcode=0): + """Change user password in LDAP.""" + if node is None: + node = current().context.ldap_node + + new_user = dict(user) + new_user['dn'] = f"cn={new_cn},ou=users,dc=company,dc=com" + new_user['cn'] = new_cn + + ldif = ( + f"dn: {user['dn']}\n" + "changetype: modrdn\n" + f"newrdn: cn = {new_user['cn']}\n" + f"deleteoldrdn: 1\n" + ) + + r = node.command( + f"echo -e \"{ldif}\" | ldapmodify -x -H ldap://localhost -D \"cn=admin,dc=company,dc=com\" -w admin") + + if exitcode is not None: + assert r.exitcode == exitcode, error() + + return new_user + +@contextmanager +def ldap_user(cn, userpassword, givenname=None, homedirectory=None, sn=None, uid=None, uidnumber=None, node=None): + """Add new user to the LDAP server.""" + try: + user = None + with Given(f"I add user {cn} to LDAP"): + user = add_user_to_ldap(cn, userpassword, givenname, homedirectory, sn, uid, uidnumber, node=node) + yield user + finally: + with Finally(f"I delete user {cn} from LDAP"): + if user is not None: + delete_user_from_ldap(user, node=node) + +@contextmanager +def ldap_users(*users, node=None): + """Add multiple new users to the LDAP server.""" + try: + _users = [] + with Given("I add users to LDAP"): + for user in users: + with By(f"adding user {user['cn']}"): + _users.append(add_user_to_ldap(**user, node=node)) + yield _users + finally: + with Finally(f"I delete users from LDAP"): + for _user in _users: + delete_user_from_ldap(_user, node=node) + +def login(servers, *users, config=None): + """Configure LDAP server and LDAP authenticated users and + try to login and execute a query""" + with ldap_servers(servers): + with ldap_authenticated_users(*users, restart=True, config=config): + for user in users: + if user.get("login", False): + with When(f"I login as {user['username']} and execute query"): + current().context.node.query("SELECT 1", + settings=[("user", user["username"]), ("password", user["password"])], + exitcode=user.get("exitcode", None), + message=user.get("message", None)) + diff --git a/tests/functional/ldap/tests/connections.py b/tests/functional/ldap/tests/connections.py new file mode 100644 index 00000000000..410298ba5e1 --- /dev/null +++ b/tests/functional/ldap/tests/connections.py @@ -0,0 +1,285 @@ +from testflows.core import * +from testflows.asserts import error + +from ldap.tests.common import login +from ldap.requirements import * + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Protocol_PlainText("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_EnableTLS("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_No("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_Port_Default("1.0") +) +def plain_text(self): + """Check that we can perform LDAP user authentication using `plain text` connection protocol. + """ + servers = { + "openldap1": { + "host": "openldap1", + "enable_tls": "no", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + } + } + users = [ + {"server": "openldap1", "username": "user1", "password": "user1", "login": True} + ] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Protocol_PlainText("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_Port("1.0") +) +def plain_text_with_custom_port(self): + """Check that we can perform LDAP user authentication using `plain text` connection protocol + with the server that uses custom port. + """ + servers = { + "openldap3": { + "host": "openldap3", + "port": "3089", + "enable_tls": "no", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + } + } + users = [ + {"server": "openldap3", "username": "user3", "password": "user3", "login": True} + ] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Protocol_TLS("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_Port("1.0") +) +def tls_with_custom_port(self): + """Check that we can perform LDAP user authentication using `TLS` connection protocol + with the server that uses custom port. + """ + servers = { + "openldap4": { + "host": "openldap4", + "port": "6036", + "tls_require_cert": "never", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + } + } + users = [ + {"server": "openldap4", "username": "user4", "password": "user4", "login": True} + ] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Authentication_Protocol_StartTLS("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_Port("1.0") +) +def starttls_with_custom_port(self): + """Check that we can perform LDAP user authentication using `StartTLS` connection protocol + with the server that uses custom port. + """ + servers = { + "openldap4": { + "host": "openldap4", + "port": "3089", + "enable_tls": "starttls", + "tls_require_cert": "never", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + } + } + users = [ + {"server": "openldap4", "username": "user4", "password": "user4", "login": True} + ] + login(servers, *users) + +def tls_connection(enable_tls, tls_require_cert): + """Try to login using LDAP user authentication over a TLS connection.""" + servers = { + "openldap2": { + "host": "openldap2", + "enable_tls": enable_tls, + "tls_require_cert": tls_require_cert, + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + } + } + users = [ + {"server": "openldap2", "username": "user2", "password": "user2", "login": True} + ] + + requirements = [] + + if tls_require_cert == "never": + requirements = [RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Never("1.0")] + elif tls_require_cert == "allow": + requirements = [RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Allow("1.0")] + elif tls_require_cert == "try": + requirements = [RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Try("1.0")] + elif tls_require_cert == "demand": + requirements = [RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Demand("1.0")] + + with Example(name=f"tls_require_cert='{tls_require_cert}'", requirements=requirements): + login(servers, *users) + +@TestScenario +@Examples("enable_tls tls_require_cert", [ + ("yes", "never"), + ("yes", "allow"), + ("yes", "try"), + ("yes", "demand") +]) +@Requirements( + RQ_SRS_007_LDAP_Authentication_Protocol_TLS("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_EnableTLS("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_Yes("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_Port_Default("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_TLSMinimumProtocolVersion_Default("1.0") +) +def tls(self): + """Check that we can perform LDAP user authentication using `TLS` connection protocol. + """ + for example in self.examples: + tls_connection(*example) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_Default("1.0") +) +def tls_enable_tls_default_yes(self): + """Check that the default value for the `enable_tls` is set to `yes`.""" + servers = { + "openldap2": { + "host": "openldap2", + "tls_require_cert": "never", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + } + } + users = [ + {"server": "openldap2", "username": "user2", "password": "user2", "login": True} + ] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Configuration_Server_TLSRequireCert_Options_Default("1.0") +) +def tls_require_cert_default_demand(self): + """Check that the default value for the `tls_require_cert` is set to `demand`.""" + servers = { + "openldap2": { + "host": "openldap2", + "enable_tls": "yes", + "port": "636", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + } + } + users = [ + {"server": "openldap2", "username": "user2", "password": "user2", "login": True} + ] + login(servers, *users) + +@TestScenario +@Examples("enable_tls tls_require_cert", [ + ("starttls", "never"), + ("starttls", "allow"), + ("starttls", "try"), + ("starttls", "demand") +]) +@Requirements( + RQ_SRS_007_LDAP_Authentication_Protocol_StartTLS("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_EnableTLS("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_EnableTLS_Options_StartTLS("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_Port_Default("1.0") +) +def starttls(self): + """Check that we can perform LDAP user authentication using legacy `StartTLS` connection protocol. + """ + for example in self.examples: + tls_connection(*example) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Configuration_Server_TLSCipherSuite("1.0") +) +def tls_cipher_suite(self): + """Check that `tls_cipher_suite` parameter can be used specify allowed cipher suites.""" + servers = { + "openldap4": { + "host": "openldap4", + "port": "6036", + "tls_require_cert": "never", + "tls_cipher_suite": "SECURE256:+SECURE128:-VERS-TLS-ALL:+VERS-TLS1.2:-RSA:-DHE-DSS:-CAMELLIA-128-CBC:-CAMELLIA-256-CBC", + "tls_minimum_protocol_version": "tls1.2", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + } + } + users = [ + {"server": "openldap4", "username": "user4", "password": "user4", "login": True} + ] + login(servers, *users) + +@TestOutline(Scenario) +@Requirements( + RQ_SRS_007_LDAP_Configuration_Server_TLSMinimumProtocolVersion("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_TLSMinimumProtocolVersion_Values("1.0") +) +@Examples("version exitcode message", [ + ("ssl2", None, None), + ("ssl3", None, None), + ("tls1.0", None, None), + ("tls1.1", None, None), + ("tls1.2", None, None), + ("tls1.3", 36, "DB::Exception: LDAP server 'openldap4' is not configured") +]) +def tls_minimum_protocol_version(self, version, exitcode, message): + """Check that `tls_minimum_protocol_version` parameter can be used specify + to specify the minimum protocol version of SSL/TLS.""" + + servers = { + "openldap4": { + "host": "openldap4", + "port": "6036", + "tls_require_cert": "never", + "tls_minimum_protocol_version": version, + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + } + } + + users = [{ + "server": "openldap4", "username": "user4", "password": "user4", + "login": True, "exitcode": int(exitcode) if exitcode is not None else None, "message": message + }] + + # Note: this code was an attempt to produce a negative case but did not work + # ldap_node = self.context.cluster.node("openldap4") + # ldif = ( + # "dn: cn=config\n" + # "changetype: modify\n" + # "replace: olcTLSProtocolMin\n" + # "olcTLSProtocolMin: 3.5" + # ) + # + # r = ldap_node.command( + # f"echo -e \"{ldif}\" | ldapmodify -x -H ldaps://localhost:6036 -D \"cn=admin,cn=config\" -w config") + # + # ldap_node.restart() + + login(servers, *users) + +@TestFeature +@Name("connection protocols") +def feature(self, node="clickhouse1"): + self.context.node = self.context.cluster.node(node) + + for scenario in loads(current_module(), Scenario): + scenario() diff --git a/tests/functional/ldap/tests/multiple_servers.py b/tests/functional/ldap/tests/multiple_servers.py new file mode 100644 index 00000000000..aefc0116fa2 --- /dev/null +++ b/tests/functional/ldap/tests/multiple_servers.py @@ -0,0 +1,38 @@ +from testflows.core import * +from testflows.asserts import error + +from ldap.tests.common import login +from ldap.requirements import RQ_SRS_007_LDAP_Authentication_MultipleServers + +@TestScenario +@Name("multiple servers") +@Requirements( + RQ_SRS_007_LDAP_Authentication_MultipleServers("1.0") +) +def scenario(self, node="clickhouse1"): + """Check that multiple LDAP servers can be used to + authenticate users. + """ + self.context.node = self.context.cluster.node(node) + servers = { + "openldap1": { + "host": "openldap1", + "port": "389", + "enable_tls": "no", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }, + "openldap2": { + "host": "openldap2", + "port": "636", + "enable_tls": "yes", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com", + "tls_require_cert": "never", + }, + } + users = [ + {"server": "openldap1", "username": "user1", "password": "user1", "login": True}, + {"server": "openldap2", "username": "user2", "password": "user2", "login": True} + ] + login(servers, *users) diff --git a/tests/functional/ldap/tests/sanity.py b/tests/functional/ldap/tests/sanity.py new file mode 100644 index 00000000000..9e5d8a2ddd7 --- /dev/null +++ b/tests/functional/ldap/tests/sanity.py @@ -0,0 +1,42 @@ +from testflows.core import * +from testflows.asserts import error + +from ldap.tests.common import add_user_to_ldap, delete_user_from_ldap + +@TestScenario +@Name("sanity") +def scenario(self, server="openldap1"): + """Check that LDAP server is up and running by + executing ldapsearch, ldapadd, and ldapdelete commands. + """ + self.context.ldap_node = self.context.cluster.node(server) + + with When("I search LDAP database"): + r = self.context.ldap_node.command( + "ldapsearch -x -H ldap://localhost -b \"dc=company,dc=com\" -D \"cn=admin,dc=company,dc=com\" -w admin") + assert r.exitcode == 0, error() + + with Then("I should find an entry for user1"): + assert "dn: cn=user1,ou=users,dc=company,dc=com" in r.output, error() + + with When("I add new user to LDAP"): + user = add_user_to_ldap(cn="myuser", userpassword="myuser") + + with And("I search LDAP database again"): + r = self.context.ldap_node.command( + "ldapsearch -x -H ldap://localhost -b \"dc=company,dc=com\" -D \"cn=admin,dc=company,dc=com\" -w admin") + assert r.exitcode == 0, error() + + with Then("I should find an entry for the new user"): + assert f"dn: {user['dn']}" in r.output, error() + + with When("I delete user from LDAP"): + delete_user_from_ldap(user) + + with And("I search LDAP database again"): + r = self.context.ldap_node.command( + "ldapsearch -x -H ldap://localhost -b \"dc=company,dc=com\" -D \"cn=admin,dc=company,dc=com\" -w admin") + assert r.exitcode == 0, error() + + with Then("I should not find an entry for the deleted user"): + assert f"dn: {user['dn']}" not in r.output, error() diff --git a/tests/functional/ldap/tests/server_config.py b/tests/functional/ldap/tests/server_config.py new file mode 100644 index 00000000000..eae36973c54 --- /dev/null +++ b/tests/functional/ldap/tests/server_config.py @@ -0,0 +1,263 @@ +from testflows.core import * + +from ldap.tests.common import * +from ldap.requirements import * + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_Name("1.0") +) +def empty_server_name(self, timeout=20): + """Check that empty string as a server name is not allowed. + """ + servers = {"": {"host": "foo", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }} + invalid_server_config(servers, timeout=timeout) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0"), + RQ_SRS_007_LDAP_UnreachableServer("1.0") +) +def invalid_host(self): + """Check that server returns an error when LDAP server + host name is invalid. + """ + servers = {"foo": {"host": "foo", "port": "389", "enable_tls": "no"}} + users = [{ + "server": "foo", "username": "user1", "password": "user1", "login": True, + "exitcode": 17, "message": "DB::Exception: Can't contact LDAP server" + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_Host("1.0") +) +def empty_host(self): + """Check that server returns an error when LDAP server + host value is empty. + """ + servers = {"foo": {"host": "", "port": "389", "enable_tls": "no"}} + users = [{ + "server": "foo", "username": "user1", "password": "user1", "login": True, + "exitcode": 36, "message": "DB::Exception: LDAP server 'foo' is not configured." + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_Host("1.0") +) +def missing_host(self): + """Check that server returns an error when LDAP server + host is missing. + """ + servers = {"foo": {"port": "389", "enable_tls": "no"}} + users = [{ + "server": "foo", "username": "user1", "password": "user1", "login": True, + "exitcode": 36, "message": "DB::Exception: LDAP server 'foo' is not configured." + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0") +) +def invalid_port(self): + """Check that server returns an error when LDAP server + port is not valid. + """ + servers = {"openldap1": {"host": "openldap1", "port": "3890", "enable_tls": "no"}} + users = [{ + "server": "openldap1", "username": "user1", "password": "user1", "login": True, + "exitcode": 17, "message": "DB::Exception: Can't contact LDAP server." + }] + login(servers, *users) + + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0") +) +def invalid_auth_dn_prefix(self): + """Check that server returns an error when LDAP server + port is not valid. + """ + servers = {"openldap1": {"host": "openldap1", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "foo=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }} + users = [{ + "server": "openldap1", "username": "user1", "password": "user1", "login": True, + "exitcode": 17, "message": "DB::Exception: Invalid DN syntax: invalid DN" + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0") +) +def invalid_auth_dn_suffix(self): + """Check that server returns an error when LDAP server + port is not valid. + """ + servers = {"openldap1": {"host": "openldap1", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",foo=users,dc=company,dc=com" + }} + users = [{ + "server": "openldap1", "username": "user1", "password": "user1", "login": True, + "exitcode": 17, "message": "DB::Exception: Invalid DN syntax: invalid DN" + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0") +) +def invalid_enable_tls_value(self): + """Check that server returns an error when enable_tls + option has invalid value. + """ + servers = {"openldap1": {"host": "openldap1", "port": "389", "enable_tls": "foo", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }} + users = [{ + "server": "openldap1", "username": "user1", "password": "user1", "login": True, + "exitcode": 36, "message": "DB::Exception: LDAP server 'openldap1' is not configured" + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0") +) +def invalid_tls_require_cert_value(self): + """Check that server returns an error when tls_require_cert + option has invalid value. + """ + servers = {"openldap2": { + "host": "openldap2", "port": "636", "enable_tls": "yes", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com", + "tls_require_cert": "foo", + "ca_cert_dir": "/container/service/slapd/assets/certs/", + "ca_cert_file": "/container/service/slapd/assets/certs/ca.crt" + }} + users = [{ + "server": "openldap2", "username": "user2", "password": "user2", "login": True, + "exitcode": 36, "message": "DB::Exception: LDAP server 'openldap2' is not configured" + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0") +) +def empty_ca_cert_dir(self): + """Check that server returns an error when ca_cert_dir is empty. + """ + servers = {"openldap2": {"host": "openldap2", "port": "636", "enable_tls": "yes", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com", + "tls_require_cert": "demand", + "ca_cert_dir": "", + "ca_cert_file": "/container/service/slapd/assets/certs/ca.crt" + }} + users = [{ + "server": "openldap2", "username": "user2", "password": "user2", "login": True, + "exitcode": 17, + "message": "DB::Exception: Can't contact LDAP server: error:14000086:SSL routines::certificate verify failed (self signed certificate in certificate chain" + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Server_Configuration_Invalid("1.0") +) +def empty_ca_cert_file(self): + """Check that server returns an error when ca_cert_file is empty. + """ + servers = {"openldap2": {"host": "openldap2", "port": "636", "enable_tls": "yes", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com", + "tls_require_cert": "demand", + "ca_cert_dir": "/container/service/slapd/assets/certs/", + "ca_cert_file": "" + }} + users = [{ + "server": "openldap2", "username": "user2", "password": "user2", "login": True, + "exitcode": 17, + "message": "Received from localhost:9000. DB::Exception: Can't contact LDAP server: error:14000086:SSL routines::certificate verify failed (self signed certificate in certificate chain)" + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Configuration_Server_AuthDN_Value("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_AuthDN_Prefix("1.0"), + RQ_SRS_007_LDAP_Configuration_Server_AuthDN_Suffix("1.0") +) +def auth_dn_value(self): + """Check that server configuration can properly define the `dn` value of the user.""" + servers = { + "openldap1": { + "host": "openldap1", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }} + user = {"server": "openldap1", "username": "user1", "password": "user1", "login": True} + + login(servers, user) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Configuration_Server_Syntax("1.0") +) +def syntax(self): + """Check that server configuration with valid syntax can be loaded. + ```xml + + + localhost + 636 + cn= + , ou=users, dc=example, dc=com + yes + tls1.2 + demand + /path/to/tls_cert_file + /path/to/tls_key_file + /path/to/tls_ca_cert_file + /path/to/tls_ca_cert_dir + ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:AES256-GCM-SHA384 + + + ``` + """ + servers = { + "openldap2": { + "host": "openldap2", + "port": "389", + "auth_dn_prefix": "cn=", + "auth_dn_suffix": ",ou=users,dc=company,dc=com", + "enable_tls": "yes", + "tls_minimum_protocol_version": "tls1.2" , + "tls_require_cert": "demand", + "tls_cert_file": "/container/service/slapd/assets/certs/ldap.crt", + "tls_key_file": "/container/service/slapd/assets/certs/ldap.key", + "tls_ca_cert_file": "/container/service/slapd/assets/certs/ca.crt", + "tls_ca_cert_dir": "/container/service/slapd/assets/certs/", + "tls_cipher_suite": "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:AES256-GCM-SHA384" + } + } + with ldap_servers(servers): + pass + +@TestFeature +@Name("server config") +def feature(self, node="clickhouse1"): + """Check that LDAP server configuration. + """ + self.context.node = self.context.cluster.node(node) + for scenario in loads(current_module(), Scenario): + scenario() diff --git a/tests/functional/ldap/tests/user_config.py b/tests/functional/ldap/tests/user_config.py new file mode 100644 index 00000000000..edc85a5877e --- /dev/null +++ b/tests/functional/ldap/tests/user_config.py @@ -0,0 +1,162 @@ +import xml.etree.ElementTree as xmltree + +from testflows.core import * + +from ldap.tests.common import * +from ldap.requirements import * + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_User_Configuration_Invalid("1.0"), + RQ_SRS_007_LDAP_Configuration_User_Name_Empty("1.0") +) +def empty_user_name(self, timeout=20): + """Check that empty string as a user name is not allowed. + """ + servers = {"openldap1": { + "host": "openldap1", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }} + users = [{"server": "openldap1", "username": "", "password": "user1", "login": True}] + config = create_ldap_users_config_content(*users) + invalid_user_config(servers, config, timeout=timeout) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_User_Configuration_Invalid("1.0"), + RQ_SRS_007_LDAP_Configuration_User_LDAP_InvalidServerName_Empty("1.0") +) +def empty_server_name(self, timeout=20): + """Check that if server name is an empty string then login is not allowed. + """ + servers = {"openldap1": { + "host": "openldap1", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }} + users = [{"server": "", "username": "user1", "password": "user1", "login": True, + "errorcode": 4, + "message": "DB::Exception: user1: Authentication failed: password is incorrect or there is no user with such name" + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_User_Configuration_Invalid("1.0"), + RQ_SRS_007_LDAP_Configuration_User_LDAP_InvalidServerName_NotDefined("1.0") +) +def empty_server_not_defined(self, timeout=20): + """Check that if server is not defined then login is not allowed. + """ + servers = {"openldap1": { + "host": "openldap1", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }} + users = [{"server": "foo", "username": "user1", "password": "user1", "login": True, + "errorcode": 36, + "message": "DB::Exception: LDAP server 'foo' is not configured" + }] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Configuration_User_Syntax("1.0") +) +def valid_user_config(self): + """Check syntax of valid user configuration of LDAP authenticated user.""" + servers = {"openldap1": { + "host": "openldap1", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }} + users = [{"server": "openldap1", "username": "user1", "password": "user1", "login": True}] + login(servers, *users) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Configuration_User_OnlyOneServer("1.0") +) +def multiple_servers(self, timeout=20): + """Check that user configuration allows to specify only one LDAP server for a given user + and if multiple servers are specified then the first one is used.""" + servers = { + "openldap1": { + "host": "openldap1", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }, + "openldap2": { + "host": "openldap2", "enable_tls": "yes", "tls_require_cert": "never", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }, + } + user = {"server": "openldap1", "username": "user1", "password": "user1", "login": True} + + with When("I first create regular user configuration file"): + config = create_ldap_users_config_content(user) + + with And("I modify it to add another server"): + root = xmltree.fromstring(config.content) + xml_users = root.find("users") + xml_users.append(xmltree.Comment(text=f"LDAP users {config.uid}")) + xml_user_ldap = xml_users.find(user["username"]).find("ldap") + xml_append(xml_user_ldap, "server", "openldap2") + xml_indent(root) + content = xml_with_utf8 + str(xmltree.tostring(root, short_empty_elements=False, encoding="utf-8"), "utf-8") + + new_config = Config(content, config.path, config.name, config.uid, config.preprocessed_name) + + with Then("I login and expect it to work as the first server shall be used"): + login(servers, user, config=new_config) + +@TestScenario +@Requirements( + RQ_SRS_007_LDAP_Configuration_User_BothPasswordAndLDAP("1.0") +) +def ldap_and_password(self): + """Check that user can't be authenticated if both `ldap` and `password` + is specified for the same user. We expect an error message to be present in the log + and login attempt to fail. + """ + node = self.context.node + servers = { + "openldap1": { + "host": "openldap1", "port": "389", "enable_tls": "no", + "auth_dn_prefix": "cn=", "auth_dn_suffix": ",ou=users,dc=company,dc=com" + }, + } + user = { + "server": "openldap1", "username": "user1", "password": "user1", "login": True, + "errorcode": 4, + "message": "DB::Exception: user1: Authentication failed: password is incorrect or there is no user with such name" + } + + with When("I first create regular user configuration file"): + config = create_ldap_users_config_content(user) + + with And("I modify it to add explicit password"): + root = xmltree.fromstring(config.content) + xml_users = root.find("users") + xml_users.append(xmltree.Comment(text=f"LDAP users {config.uid}")) + xml_user = xml_users.find(user["username"]) + xml_append(xml_user, "password", "hellothere") + xml_indent(root) + content = xml_with_utf8 + str(xmltree.tostring(root, short_empty_elements=False, encoding="utf-8"), "utf-8") + + new_config = Config(content, config.path, config.name, config.uid, config.preprocessed_name) + + error_message = "DB::Exception: More than one field of 'password'" + + with Then("I expect an error when I try to load the configuration file", description=error_message): + invalid_user_config(servers, new_config, message=error_message, tail=16) + + with And("I expect the authentication to fail when I try to login"): + login(servers, user, config=new_config) + +@TestFeature +@Name("user config") +def feature(self, node="clickhouse1"): + """Check that server returns an error and prohibits + user login if LDAP users configuration is not valid. + """ + self.context.node = self.context.cluster.node(node) + + for scenario in loads(current_module(), Scenario): + scenario() diff --git a/tests/functional/regression.py b/tests/functional/regression.py new file mode 100755 index 00000000000..21c55540509 --- /dev/null +++ b/tests/functional/regression.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +import sys +from testflows.core import * + +append_path(sys.path, "."), + +from helpers.argparser import argparser + +@TestModule +@Name("clickhouse") +@ArgumentParser(argparser) +def regression(self, local, clickhouse_binary_path): + """ClickHouse functional regression module. + """ + Feature(test=load("ldap.regression", "regression"))( + local=local, clickhouse_binary_path=clickhouse_binary_path) + +if main(): + regression() From 45d819949a33ad43547790a6729d7187c1962272 Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Thu, 2 Jul 2020 17:08:35 +0200 Subject: [PATCH 033/143] * Moving testflows tests into tests/testflows directory. * Adding a simple README.md. --- tests/testflows/README.md | 50 +++++++++++++++++++ .../helpers/argparser.py | 0 .../helpers/cluster.py | 0 .../ldap/__init__.py | 0 .../ldap/configs/CA/ca.crt | 0 .../ldap/configs/CA/ca.key | 0 .../ldap/configs/CA/ca.srl | 0 .../ldap/configs/CA/dhparam.pem | 0 .../ldap/configs/CA/passphrase.txt | 0 .../ldap/configs/clickhouse/common.xml | 0 .../ldap/configs/clickhouse/config.d/logs.xml | 0 .../configs/clickhouse/config.d/ports.xml | 0 .../configs/clickhouse/config.d/remote.xml | 0 .../ldap/configs/clickhouse/config.d/ssl.xml | 0 .../configs/clickhouse/config.d/storage.xml | 0 .../configs/clickhouse/config.d/zookeeper.xml | 0 .../ldap/configs/clickhouse/config.xml | 0 .../ldap/configs/clickhouse/ssl/dhparam.pem | 0 .../ldap/configs/clickhouse/ssl/server.crt | 0 .../ldap/configs/clickhouse/ssl/server.key | 0 .../ldap/configs/clickhouse/users.xml | 0 .../configs/clickhouse1/config.d/macros.xml | 0 .../configs/clickhouse2/config.d/macros.xml | 0 .../configs/clickhouse3/config.d/macros.xml | 0 .../ldap/configs/ldap1/config/export.ldif | 0 .../ldap/configs/ldap2/certs/ca.crt | 0 .../ldap/configs/ldap2/certs/dhparam.pem | 0 .../ldap/configs/ldap2/certs/ldap.crt | 0 .../ldap/configs/ldap2/certs/ldap.csr | 0 .../ldap/configs/ldap2/certs/ldap.key | 0 .../ldap/configs/ldap2/config/export.ldif | 0 .../ldap/configs/ldap3/certs/ca.crt | 0 .../ldap/configs/ldap3/certs/dhparam.pem | 0 .../ldap/configs/ldap3/certs/ldap.crt | 0 .../ldap/configs/ldap3/certs/ldap.csr | 0 .../ldap/configs/ldap3/certs/ldap.key | 0 .../ldap/configs/ldap3/config/export.ldif | 0 .../ldap/configs/ldap4/config/export.ldif | 0 .../ldap/configs/ldap5/config/export.ldif | 0 .../ldap/configs/ldap5/ldap2/certs/ca.crt | 0 .../configs/ldap5/ldap2/certs/dhparam.pem | 0 .../ldap/configs/ldap5/ldap2/certs/ldap.crt | 0 .../ldap/configs/ldap5/ldap2/certs/ldap.csr | 0 .../ldap/configs/ldap5/ldap2/certs/ldap.key | 0 .../configs/ldap5/ldap2/config/export.ldif | 0 .../docker-compose/clickhouse-service.yml | 0 .../ldap/docker-compose/docker-compose.yml | 0 .../ldap/docker-compose/openldap-service.yml | 0 .../ldap/docker-compose/zookeeper-service.yml | 0 .../ldap/regression.py | 0 .../ldap/requirements/__init__.py | 0 .../ldap/requirements/requirements.py | 0 .../ldap/tests/authentications.py | 0 .../ldap/tests/common.py | 0 .../ldap/tests/connections.py | 0 .../ldap/tests/multiple_servers.py | 0 .../ldap/tests/sanity.py | 0 .../ldap/tests/server_config.py | 0 .../ldap/tests/user_config.py | 0 tests/{functional => testflows}/regression.py | 0 60 files changed, 50 insertions(+) create mode 100644 tests/testflows/README.md rename tests/{functional => testflows}/helpers/argparser.py (100%) rename tests/{functional => testflows}/helpers/cluster.py (100%) rename tests/{functional => testflows}/ldap/__init__.py (100%) rename tests/{functional => testflows}/ldap/configs/CA/ca.crt (100%) rename tests/{functional => testflows}/ldap/configs/CA/ca.key (100%) rename tests/{functional => testflows}/ldap/configs/CA/ca.srl (100%) rename tests/{functional => testflows}/ldap/configs/CA/dhparam.pem (100%) rename tests/{functional => testflows}/ldap/configs/CA/passphrase.txt (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/common.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/config.d/logs.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/config.d/ports.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/config.d/remote.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/config.d/ssl.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/config.d/storage.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/config.d/zookeeper.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/config.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/ssl/dhparam.pem (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/ssl/server.crt (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/ssl/server.key (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse/users.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse1/config.d/macros.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse2/config.d/macros.xml (100%) rename tests/{functional => testflows}/ldap/configs/clickhouse3/config.d/macros.xml (100%) rename tests/{functional => testflows}/ldap/configs/ldap1/config/export.ldif (100%) rename tests/{functional => testflows}/ldap/configs/ldap2/certs/ca.crt (100%) rename tests/{functional => testflows}/ldap/configs/ldap2/certs/dhparam.pem (100%) rename tests/{functional => testflows}/ldap/configs/ldap2/certs/ldap.crt (100%) rename tests/{functional => testflows}/ldap/configs/ldap2/certs/ldap.csr (100%) rename tests/{functional => testflows}/ldap/configs/ldap2/certs/ldap.key (100%) rename tests/{functional => testflows}/ldap/configs/ldap2/config/export.ldif (100%) rename tests/{functional => testflows}/ldap/configs/ldap3/certs/ca.crt (100%) rename tests/{functional => testflows}/ldap/configs/ldap3/certs/dhparam.pem (100%) rename tests/{functional => testflows}/ldap/configs/ldap3/certs/ldap.crt (100%) rename tests/{functional => testflows}/ldap/configs/ldap3/certs/ldap.csr (100%) rename tests/{functional => testflows}/ldap/configs/ldap3/certs/ldap.key (100%) rename tests/{functional => testflows}/ldap/configs/ldap3/config/export.ldif (100%) rename tests/{functional => testflows}/ldap/configs/ldap4/config/export.ldif (100%) rename tests/{functional => testflows}/ldap/configs/ldap5/config/export.ldif (100%) rename tests/{functional => testflows}/ldap/configs/ldap5/ldap2/certs/ca.crt (100%) rename tests/{functional => testflows}/ldap/configs/ldap5/ldap2/certs/dhparam.pem (100%) rename tests/{functional => testflows}/ldap/configs/ldap5/ldap2/certs/ldap.crt (100%) rename tests/{functional => testflows}/ldap/configs/ldap5/ldap2/certs/ldap.csr (100%) rename tests/{functional => testflows}/ldap/configs/ldap5/ldap2/certs/ldap.key (100%) rename tests/{functional => testflows}/ldap/configs/ldap5/ldap2/config/export.ldif (100%) rename tests/{functional => testflows}/ldap/docker-compose/clickhouse-service.yml (100%) rename tests/{functional => testflows}/ldap/docker-compose/docker-compose.yml (100%) rename tests/{functional => testflows}/ldap/docker-compose/openldap-service.yml (100%) rename tests/{functional => testflows}/ldap/docker-compose/zookeeper-service.yml (100%) rename tests/{functional => testflows}/ldap/regression.py (100%) rename tests/{functional => testflows}/ldap/requirements/__init__.py (100%) rename tests/{functional => testflows}/ldap/requirements/requirements.py (100%) rename tests/{functional => testflows}/ldap/tests/authentications.py (100%) rename tests/{functional => testflows}/ldap/tests/common.py (100%) rename tests/{functional => testflows}/ldap/tests/connections.py (100%) rename tests/{functional => testflows}/ldap/tests/multiple_servers.py (100%) rename tests/{functional => testflows}/ldap/tests/sanity.py (100%) rename tests/{functional => testflows}/ldap/tests/server_config.py (100%) rename tests/{functional => testflows}/ldap/tests/user_config.py (100%) rename tests/{functional => testflows}/regression.py (100%) diff --git a/tests/testflows/README.md b/tests/testflows/README.md new file mode 100644 index 00000000000..e7ad3f9370f --- /dev/null +++ b/tests/testflows/README.md @@ -0,0 +1,50 @@ +## ClickHouse Tests in [TestFlows] + +This directory contains integration tests written using [TestFlows] +that involves several ClickHouse instances, custom configs, ZooKeeper, etc. + +## Supported environment + +* [Ubuntu] 18.04 +* [Python 3] >= 3.6 + +## Prerequisites + +* [Docker] [install](https://docs.docker.com/compose/install/) +* [Docker Compose] [install](https://docs.docker.com/engine/install/) +* [TestFlows] [install](https://testflows.com/handbook/#Installation) + +## Running tests locally + +You can run tests locally by passing `--local` and `--clickhouse-binary-path` to the `regression.py`. + +* `--local` specifies that regression will be run locally +* `--clickhouse-binary-path` specifies the path to the ClickHouse binary that will be used during the regression run + +> Note: you can pass `-h` or `--help` argument to the `regression.py` to see a help message. +> +> ```bash +> python3 regression.py -h +> ``` + +> Note: make sure that the ClickHouse binary has correct permissions. +> If you are using `/usr/bin/clickhouse` its owner and group is set to `root:root` by default +> and it needs to be changed to `clickhouse:clickhouse`. You can change the owner and the group +> using the following command. +> +> ```bash +> sudo chown clickhouse:clickhouse /usr/bin/clickhouse +> ``` + +Using the default ClickHouse installation and its server binary at `/usr/bin/clickhouse`, you can run +regressions locally using the following command. + +```bash +python3 regression.py --local --clickhouse-binary-path "/usr/bin/clickhouse" +``` + +[Python 3]: https://www.python.org/ +[Ubuntu]: https://ubuntu.com/ +[TestFlows]: https://testflows.com +[Docker]: https://www.docker.com/ +[Docker Compose]: https://docs.docker.com/compose/ diff --git a/tests/functional/helpers/argparser.py b/tests/testflows/helpers/argparser.py similarity index 100% rename from tests/functional/helpers/argparser.py rename to tests/testflows/helpers/argparser.py diff --git a/tests/functional/helpers/cluster.py b/tests/testflows/helpers/cluster.py similarity index 100% rename from tests/functional/helpers/cluster.py rename to tests/testflows/helpers/cluster.py diff --git a/tests/functional/ldap/__init__.py b/tests/testflows/ldap/__init__.py similarity index 100% rename from tests/functional/ldap/__init__.py rename to tests/testflows/ldap/__init__.py diff --git a/tests/functional/ldap/configs/CA/ca.crt b/tests/testflows/ldap/configs/CA/ca.crt similarity index 100% rename from tests/functional/ldap/configs/CA/ca.crt rename to tests/testflows/ldap/configs/CA/ca.crt diff --git a/tests/functional/ldap/configs/CA/ca.key b/tests/testflows/ldap/configs/CA/ca.key similarity index 100% rename from tests/functional/ldap/configs/CA/ca.key rename to tests/testflows/ldap/configs/CA/ca.key diff --git a/tests/functional/ldap/configs/CA/ca.srl b/tests/testflows/ldap/configs/CA/ca.srl similarity index 100% rename from tests/functional/ldap/configs/CA/ca.srl rename to tests/testflows/ldap/configs/CA/ca.srl diff --git a/tests/functional/ldap/configs/CA/dhparam.pem b/tests/testflows/ldap/configs/CA/dhparam.pem similarity index 100% rename from tests/functional/ldap/configs/CA/dhparam.pem rename to tests/testflows/ldap/configs/CA/dhparam.pem diff --git a/tests/functional/ldap/configs/CA/passphrase.txt b/tests/testflows/ldap/configs/CA/passphrase.txt similarity index 100% rename from tests/functional/ldap/configs/CA/passphrase.txt rename to tests/testflows/ldap/configs/CA/passphrase.txt diff --git a/tests/functional/ldap/configs/clickhouse/common.xml b/tests/testflows/ldap/configs/clickhouse/common.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse/common.xml rename to tests/testflows/ldap/configs/clickhouse/common.xml diff --git a/tests/functional/ldap/configs/clickhouse/config.d/logs.xml b/tests/testflows/ldap/configs/clickhouse/config.d/logs.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse/config.d/logs.xml rename to tests/testflows/ldap/configs/clickhouse/config.d/logs.xml diff --git a/tests/functional/ldap/configs/clickhouse/config.d/ports.xml b/tests/testflows/ldap/configs/clickhouse/config.d/ports.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse/config.d/ports.xml rename to tests/testflows/ldap/configs/clickhouse/config.d/ports.xml diff --git a/tests/functional/ldap/configs/clickhouse/config.d/remote.xml b/tests/testflows/ldap/configs/clickhouse/config.d/remote.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse/config.d/remote.xml rename to tests/testflows/ldap/configs/clickhouse/config.d/remote.xml diff --git a/tests/functional/ldap/configs/clickhouse/config.d/ssl.xml b/tests/testflows/ldap/configs/clickhouse/config.d/ssl.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse/config.d/ssl.xml rename to tests/testflows/ldap/configs/clickhouse/config.d/ssl.xml diff --git a/tests/functional/ldap/configs/clickhouse/config.d/storage.xml b/tests/testflows/ldap/configs/clickhouse/config.d/storage.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse/config.d/storage.xml rename to tests/testflows/ldap/configs/clickhouse/config.d/storage.xml diff --git a/tests/functional/ldap/configs/clickhouse/config.d/zookeeper.xml b/tests/testflows/ldap/configs/clickhouse/config.d/zookeeper.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse/config.d/zookeeper.xml rename to tests/testflows/ldap/configs/clickhouse/config.d/zookeeper.xml diff --git a/tests/functional/ldap/configs/clickhouse/config.xml b/tests/testflows/ldap/configs/clickhouse/config.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse/config.xml rename to tests/testflows/ldap/configs/clickhouse/config.xml diff --git a/tests/functional/ldap/configs/clickhouse/ssl/dhparam.pem b/tests/testflows/ldap/configs/clickhouse/ssl/dhparam.pem similarity index 100% rename from tests/functional/ldap/configs/clickhouse/ssl/dhparam.pem rename to tests/testflows/ldap/configs/clickhouse/ssl/dhparam.pem diff --git a/tests/functional/ldap/configs/clickhouse/ssl/server.crt b/tests/testflows/ldap/configs/clickhouse/ssl/server.crt similarity index 100% rename from tests/functional/ldap/configs/clickhouse/ssl/server.crt rename to tests/testflows/ldap/configs/clickhouse/ssl/server.crt diff --git a/tests/functional/ldap/configs/clickhouse/ssl/server.key b/tests/testflows/ldap/configs/clickhouse/ssl/server.key similarity index 100% rename from tests/functional/ldap/configs/clickhouse/ssl/server.key rename to tests/testflows/ldap/configs/clickhouse/ssl/server.key diff --git a/tests/functional/ldap/configs/clickhouse/users.xml b/tests/testflows/ldap/configs/clickhouse/users.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse/users.xml rename to tests/testflows/ldap/configs/clickhouse/users.xml diff --git a/tests/functional/ldap/configs/clickhouse1/config.d/macros.xml b/tests/testflows/ldap/configs/clickhouse1/config.d/macros.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse1/config.d/macros.xml rename to tests/testflows/ldap/configs/clickhouse1/config.d/macros.xml diff --git a/tests/functional/ldap/configs/clickhouse2/config.d/macros.xml b/tests/testflows/ldap/configs/clickhouse2/config.d/macros.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse2/config.d/macros.xml rename to tests/testflows/ldap/configs/clickhouse2/config.d/macros.xml diff --git a/tests/functional/ldap/configs/clickhouse3/config.d/macros.xml b/tests/testflows/ldap/configs/clickhouse3/config.d/macros.xml similarity index 100% rename from tests/functional/ldap/configs/clickhouse3/config.d/macros.xml rename to tests/testflows/ldap/configs/clickhouse3/config.d/macros.xml diff --git a/tests/functional/ldap/configs/ldap1/config/export.ldif b/tests/testflows/ldap/configs/ldap1/config/export.ldif similarity index 100% rename from tests/functional/ldap/configs/ldap1/config/export.ldif rename to tests/testflows/ldap/configs/ldap1/config/export.ldif diff --git a/tests/functional/ldap/configs/ldap2/certs/ca.crt b/tests/testflows/ldap/configs/ldap2/certs/ca.crt similarity index 100% rename from tests/functional/ldap/configs/ldap2/certs/ca.crt rename to tests/testflows/ldap/configs/ldap2/certs/ca.crt diff --git a/tests/functional/ldap/configs/ldap2/certs/dhparam.pem b/tests/testflows/ldap/configs/ldap2/certs/dhparam.pem similarity index 100% rename from tests/functional/ldap/configs/ldap2/certs/dhparam.pem rename to tests/testflows/ldap/configs/ldap2/certs/dhparam.pem diff --git a/tests/functional/ldap/configs/ldap2/certs/ldap.crt b/tests/testflows/ldap/configs/ldap2/certs/ldap.crt similarity index 100% rename from tests/functional/ldap/configs/ldap2/certs/ldap.crt rename to tests/testflows/ldap/configs/ldap2/certs/ldap.crt diff --git a/tests/functional/ldap/configs/ldap2/certs/ldap.csr b/tests/testflows/ldap/configs/ldap2/certs/ldap.csr similarity index 100% rename from tests/functional/ldap/configs/ldap2/certs/ldap.csr rename to tests/testflows/ldap/configs/ldap2/certs/ldap.csr diff --git a/tests/functional/ldap/configs/ldap2/certs/ldap.key b/tests/testflows/ldap/configs/ldap2/certs/ldap.key similarity index 100% rename from tests/functional/ldap/configs/ldap2/certs/ldap.key rename to tests/testflows/ldap/configs/ldap2/certs/ldap.key diff --git a/tests/functional/ldap/configs/ldap2/config/export.ldif b/tests/testflows/ldap/configs/ldap2/config/export.ldif similarity index 100% rename from tests/functional/ldap/configs/ldap2/config/export.ldif rename to tests/testflows/ldap/configs/ldap2/config/export.ldif diff --git a/tests/functional/ldap/configs/ldap3/certs/ca.crt b/tests/testflows/ldap/configs/ldap3/certs/ca.crt similarity index 100% rename from tests/functional/ldap/configs/ldap3/certs/ca.crt rename to tests/testflows/ldap/configs/ldap3/certs/ca.crt diff --git a/tests/functional/ldap/configs/ldap3/certs/dhparam.pem b/tests/testflows/ldap/configs/ldap3/certs/dhparam.pem similarity index 100% rename from tests/functional/ldap/configs/ldap3/certs/dhparam.pem rename to tests/testflows/ldap/configs/ldap3/certs/dhparam.pem diff --git a/tests/functional/ldap/configs/ldap3/certs/ldap.crt b/tests/testflows/ldap/configs/ldap3/certs/ldap.crt similarity index 100% rename from tests/functional/ldap/configs/ldap3/certs/ldap.crt rename to tests/testflows/ldap/configs/ldap3/certs/ldap.crt diff --git a/tests/functional/ldap/configs/ldap3/certs/ldap.csr b/tests/testflows/ldap/configs/ldap3/certs/ldap.csr similarity index 100% rename from tests/functional/ldap/configs/ldap3/certs/ldap.csr rename to tests/testflows/ldap/configs/ldap3/certs/ldap.csr diff --git a/tests/functional/ldap/configs/ldap3/certs/ldap.key b/tests/testflows/ldap/configs/ldap3/certs/ldap.key similarity index 100% rename from tests/functional/ldap/configs/ldap3/certs/ldap.key rename to tests/testflows/ldap/configs/ldap3/certs/ldap.key diff --git a/tests/functional/ldap/configs/ldap3/config/export.ldif b/tests/testflows/ldap/configs/ldap3/config/export.ldif similarity index 100% rename from tests/functional/ldap/configs/ldap3/config/export.ldif rename to tests/testflows/ldap/configs/ldap3/config/export.ldif diff --git a/tests/functional/ldap/configs/ldap4/config/export.ldif b/tests/testflows/ldap/configs/ldap4/config/export.ldif similarity index 100% rename from tests/functional/ldap/configs/ldap4/config/export.ldif rename to tests/testflows/ldap/configs/ldap4/config/export.ldif diff --git a/tests/functional/ldap/configs/ldap5/config/export.ldif b/tests/testflows/ldap/configs/ldap5/config/export.ldif similarity index 100% rename from tests/functional/ldap/configs/ldap5/config/export.ldif rename to tests/testflows/ldap/configs/ldap5/config/export.ldif diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/ca.crt b/tests/testflows/ldap/configs/ldap5/ldap2/certs/ca.crt similarity index 100% rename from tests/functional/ldap/configs/ldap5/ldap2/certs/ca.crt rename to tests/testflows/ldap/configs/ldap5/ldap2/certs/ca.crt diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/dhparam.pem b/tests/testflows/ldap/configs/ldap5/ldap2/certs/dhparam.pem similarity index 100% rename from tests/functional/ldap/configs/ldap5/ldap2/certs/dhparam.pem rename to tests/testflows/ldap/configs/ldap5/ldap2/certs/dhparam.pem diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.crt b/tests/testflows/ldap/configs/ldap5/ldap2/certs/ldap.crt similarity index 100% rename from tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.crt rename to tests/testflows/ldap/configs/ldap5/ldap2/certs/ldap.crt diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.csr b/tests/testflows/ldap/configs/ldap5/ldap2/certs/ldap.csr similarity index 100% rename from tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.csr rename to tests/testflows/ldap/configs/ldap5/ldap2/certs/ldap.csr diff --git a/tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.key b/tests/testflows/ldap/configs/ldap5/ldap2/certs/ldap.key similarity index 100% rename from tests/functional/ldap/configs/ldap5/ldap2/certs/ldap.key rename to tests/testflows/ldap/configs/ldap5/ldap2/certs/ldap.key diff --git a/tests/functional/ldap/configs/ldap5/ldap2/config/export.ldif b/tests/testflows/ldap/configs/ldap5/ldap2/config/export.ldif similarity index 100% rename from tests/functional/ldap/configs/ldap5/ldap2/config/export.ldif rename to tests/testflows/ldap/configs/ldap5/ldap2/config/export.ldif diff --git a/tests/functional/ldap/docker-compose/clickhouse-service.yml b/tests/testflows/ldap/docker-compose/clickhouse-service.yml similarity index 100% rename from tests/functional/ldap/docker-compose/clickhouse-service.yml rename to tests/testflows/ldap/docker-compose/clickhouse-service.yml diff --git a/tests/functional/ldap/docker-compose/docker-compose.yml b/tests/testflows/ldap/docker-compose/docker-compose.yml similarity index 100% rename from tests/functional/ldap/docker-compose/docker-compose.yml rename to tests/testflows/ldap/docker-compose/docker-compose.yml diff --git a/tests/functional/ldap/docker-compose/openldap-service.yml b/tests/testflows/ldap/docker-compose/openldap-service.yml similarity index 100% rename from tests/functional/ldap/docker-compose/openldap-service.yml rename to tests/testflows/ldap/docker-compose/openldap-service.yml diff --git a/tests/functional/ldap/docker-compose/zookeeper-service.yml b/tests/testflows/ldap/docker-compose/zookeeper-service.yml similarity index 100% rename from tests/functional/ldap/docker-compose/zookeeper-service.yml rename to tests/testflows/ldap/docker-compose/zookeeper-service.yml diff --git a/tests/functional/ldap/regression.py b/tests/testflows/ldap/regression.py similarity index 100% rename from tests/functional/ldap/regression.py rename to tests/testflows/ldap/regression.py diff --git a/tests/functional/ldap/requirements/__init__.py b/tests/testflows/ldap/requirements/__init__.py similarity index 100% rename from tests/functional/ldap/requirements/__init__.py rename to tests/testflows/ldap/requirements/__init__.py diff --git a/tests/functional/ldap/requirements/requirements.py b/tests/testflows/ldap/requirements/requirements.py similarity index 100% rename from tests/functional/ldap/requirements/requirements.py rename to tests/testflows/ldap/requirements/requirements.py diff --git a/tests/functional/ldap/tests/authentications.py b/tests/testflows/ldap/tests/authentications.py similarity index 100% rename from tests/functional/ldap/tests/authentications.py rename to tests/testflows/ldap/tests/authentications.py diff --git a/tests/functional/ldap/tests/common.py b/tests/testflows/ldap/tests/common.py similarity index 100% rename from tests/functional/ldap/tests/common.py rename to tests/testflows/ldap/tests/common.py diff --git a/tests/functional/ldap/tests/connections.py b/tests/testflows/ldap/tests/connections.py similarity index 100% rename from tests/functional/ldap/tests/connections.py rename to tests/testflows/ldap/tests/connections.py diff --git a/tests/functional/ldap/tests/multiple_servers.py b/tests/testflows/ldap/tests/multiple_servers.py similarity index 100% rename from tests/functional/ldap/tests/multiple_servers.py rename to tests/testflows/ldap/tests/multiple_servers.py diff --git a/tests/functional/ldap/tests/sanity.py b/tests/testflows/ldap/tests/sanity.py similarity index 100% rename from tests/functional/ldap/tests/sanity.py rename to tests/testflows/ldap/tests/sanity.py diff --git a/tests/functional/ldap/tests/server_config.py b/tests/testflows/ldap/tests/server_config.py similarity index 100% rename from tests/functional/ldap/tests/server_config.py rename to tests/testflows/ldap/tests/server_config.py diff --git a/tests/functional/ldap/tests/user_config.py b/tests/testflows/ldap/tests/user_config.py similarity index 100% rename from tests/functional/ldap/tests/user_config.py rename to tests/testflows/ldap/tests/user_config.py diff --git a/tests/functional/regression.py b/tests/testflows/regression.py similarity index 100% rename from tests/functional/regression.py rename to tests/testflows/regression.py From e5a3002b759be56d1693d8e453ea025e9d519bcc Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Wed, 8 Jul 2020 00:05:34 +0200 Subject: [PATCH 034/143] Adding ldap regression tests. --- tests/testflows/regression.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/testflows/regression.py b/tests/testflows/regression.py index 0f74b6e82cd..850c0be2433 100755 --- a/tests/testflows/regression.py +++ b/tests/testflows/regression.py @@ -12,8 +12,10 @@ from helpers.argparser import argparser def regression(self, local, clickhouse_binary_path): """ClickHouse regression. """ - Feature(test=load("example.regression", "regression"))( - local=local, clickhouse_binary_path=clickhouse_binary_path) + args = {"local": local, "clickhouse_binary_path": clickhouse_binary_path} + + Feature(test=load("example.regression", "regression"))(**args) + Feature(test=load("ldap.regression", "regression"))(**args) if main(): regression() From 1aa45f203b1408e86a253b7140d84589a224b0fa Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 8 Jul 2020 13:40:02 +0300 Subject: [PATCH 035/143] bump CI --- programs/server/Server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/server/Server.cpp b/programs/server/Server.cpp index 387ee88e444..626315d5cdb 100644 --- a/programs/server/Server.cpp +++ b/programs/server/Server.cpp @@ -295,7 +295,7 @@ int Server::main(const std::vector & /*args*/) #endif /** Context contains all that query execution is dependent: - * settings, available functions, data types, aggregate functions, databases... + * settings, available functions, data types, aggregate functions, databases, ... */ auto shared_context = Context::createShared(); auto global_context = std::make_unique(Context::createGlobal(shared_context.get())); From 069880a003dd1c96007ed95fe109a0ceb7e65a25 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 8 Jul 2020 16:06:35 +0300 Subject: [PATCH 036/143] Prototype --- docker/test/fasttest/Dockerfile | 63 +++++++++++++++++++++++++++ docker/test/fasttest/run.sh | 76 +++++++++++++++++++++++++++++++++ tests/clickhouse-test | 2 +- 3 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 docker/test/fasttest/Dockerfile create mode 100755 docker/test/fasttest/run.sh diff --git a/docker/test/fasttest/Dockerfile b/docker/test/fasttest/Dockerfile new file mode 100644 index 00000000000..f6b83fef573 --- /dev/null +++ b/docker/test/fasttest/Dockerfile @@ -0,0 +1,63 @@ +# docker build -t yandex/clickhouse-fasttest . +FROM ubuntu:19.10 + +ARG odbc_driver_url="https://github.com/ClickHouse/clickhouse-odbc/releases/download/v1.1.4.20200302/clickhouse-odbc-1.1.4-Linux.tar.gz" + +RUN apt-get --allow-unauthenticated update -y && apt-get install --yes wget gnupg +RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - +RUN echo "deb [trusted=yes] http://apt.llvm.org/eoan/ llvm-toolchain-eoan-10 main" >> /etc/apt/sources.list + + +RUN apt-get --allow-unauthenticated update -y \ + && env DEBIAN_FRONTEND=noninteractive \ + apt-get --allow-unauthenticated install --yes --no-install-recommends \ + bash \ + fakeroot \ + ccache \ + software-properties-common \ + apt-transport-https \ + ca-certificates \ + wget \ + bash \ + fakeroot \ + cmake \ + ccache \ + llvm-10 \ + clang-10 \ + lld-10 \ + clang-tidy-10 \ + ninja-build \ + gperf \ + git \ + tzdata \ + gperf \ + rename \ + build-essential \ + zookeeper \ + zookeeperd \ + expect \ + python \ + python-lxml \ + python-termcolor \ + python-requests \ + unixodbc \ + qemu-user-static \ + sudo \ + moreutils + +RUN mkdir -p /tmp/clickhouse-odbc-tmp \ + && wget --quiet -O - ${odbc_driver_url} | tar --strip-components=1 -xz -C /tmp/clickhouse-odbc-tmp \ + && cp /tmp/clickhouse-odbc-tmp/lib64/*.so /usr/local/lib/ \ + && odbcinst -i -d -f /tmp/clickhouse-odbc-tmp/share/doc/clickhouse-odbc/config/odbcinst.ini.sample \ + && odbcinst -i -s -l -f /tmp/clickhouse-odbc-tmp/share/doc/clickhouse-odbc/config/odbc.ini.sample \ + && rm -rf /tmp/clickhouse-odbc-tmp + +# This symlink required by gcc to find lld compiler +RUN ln -s /usr/bin/lld-10 /usr/bin/ld.lld + +ENV TZ=Europe/Moscow +RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone + + +COPY run.sh / +CMD ["/bin/bash", "/run.sh"] diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh new file mode 100755 index 00000000000..0e04a419335 --- /dev/null +++ b/docker/test/fasttest/run.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +set -x -e + +ls -la + +git clone https://github.com/ClickHouse/ClickHouse.git | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/clone_log.txt +cd ClickHouse +CLICKHOUSE_DIR=`pwd` + +git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt + +CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0" + +export CCACHE_DIR=/ccache +export CCACHE_BASEDIR=/ClickHouse +export CCACHE_NOHASHDIR=true +export CCACHE_COMPILERCHECK=content +export CCACHE_MAXSIZE=15G + +ccache --show-stats ||: +ccache --zero-stats ||: + +mkdir build +cd build +CLICKHOUSE_BUILD_DIR=`pwd` +cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_COMPILER=clang++-10 -DCMAKE_C_COMPILER=clang-10 $CMAKE_LIBS_CONFIG | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/cmake_log.txt +ninja | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/build_log.txt +ninja install | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/install_log.txt + + +ccache --show-stats ||: + +mkdir -p /etc/clickhouse-server +mkdir -p /etc/clickhouse-client +mkdir -p /etc/clickhouse-server/config.d +mkdir -p /etc/clickhouse-server/users.d +cp $CLICKHOUSE_DIR/programs/server/config.xml /etc/clickhouse-server/ +cp $CLICKHOUSE_DIR/programs/server/users.xml /etc/clickhouse-server/ + +mkdir -p /etc/clickhouse-server/dict_examples +ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-server/dict_examples/ +ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/dict_examples/ +ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/dict_examples/ +ln -s /usr/share/clickhouse-test/config/zookeeper.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/listen.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/text_log.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/metric_log.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/query_masking_rules.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/ +ln -s /usr/share/clickhouse-test/config/readonly.xml /etc/clickhouse-server/users.d/ +ln -s /usr/share/clickhouse-test/config/access_management.xml /etc/clickhouse-server/users.d/ +ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/macros.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/disks.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/secure_ports.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/clusters.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/graphite.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/server.key /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/server.crt /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/dhparam.pem /etc/clickhouse-server/ +ln -sf /usr/share/clickhouse-test/config/client_config.xml /etc/clickhouse-client/config.xml + +service zookeeper start && sleep 5 + +clickhouse-server --config /etc/clickhouse-server/config.xml --daemon + +until clickhouse-client --query "SELECT 1" +do + sleep 0.1 +done + +clickhouse-test --testname --shard --zookeeper 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt diff --git a/tests/clickhouse-test b/tests/clickhouse-test index 07fe681c2c8..98e00665230 100755 --- a/tests/clickhouse-test +++ b/tests/clickhouse-test @@ -479,7 +479,7 @@ def main(args): # Keep same default values as in queries/shell_config.sh os.environ.setdefault("CLICKHOUSE_BINARY", args.binary) - #os.environ.setdefault("CLICKHOUSE_CLIENT", args.client) + os.environ.setdefault("CLICKHOUSE_CLIENT", args.client) os.environ.setdefault("CLICKHOUSE_CONFIG", args.configserver) if args.configclient: os.environ.setdefault("CLICKHOUSE_CONFIG_CLIENT", args.configclient) From 6e79e8814926ca3f9b7648865c035f7643bc7215 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 8 Jul 2020 16:49:09 +0300 Subject: [PATCH 037/143] Add curl --- docker/test/fasttest/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/test/fasttest/Dockerfile b/docker/test/fasttest/Dockerfile index f6b83fef573..3e2128ed05f 100644 --- a/docker/test/fasttest/Dockerfile +++ b/docker/test/fasttest/Dockerfile @@ -43,7 +43,8 @@ RUN apt-get --allow-unauthenticated update -y \ unixodbc \ qemu-user-static \ sudo \ - moreutils + moreutils \ + curl RUN mkdir -p /tmp/clickhouse-odbc-tmp \ && wget --quiet -O - ${odbc_driver_url} | tar --strip-components=1 -xz -C /tmp/clickhouse-odbc-tmp \ From 80d9816e00330967723605f839433db151e42204 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 8 Jul 2020 17:22:17 +0300 Subject: [PATCH 038/143] Add brotli --- docker/test/fasttest/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docker/test/fasttest/Dockerfile b/docker/test/fasttest/Dockerfile index 3e2128ed05f..bb1e92cec49 100644 --- a/docker/test/fasttest/Dockerfile +++ b/docker/test/fasttest/Dockerfile @@ -44,7 +44,8 @@ RUN apt-get --allow-unauthenticated update -y \ qemu-user-static \ sudo \ moreutils \ - curl + curl \ + brotli RUN mkdir -p /tmp/clickhouse-odbc-tmp \ && wget --quiet -O - ${odbc_driver_url} | tar --strip-components=1 -xz -C /tmp/clickhouse-odbc-tmp \ From f30e2ea4643ceb91e7c80889856e613918573b74 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 8 Jul 2020 18:25:02 +0300 Subject: [PATCH 039/143] Tmp version --- docker/images.json | 5 +++++ docker/test/fasttest/Dockerfile | 4 ++-- docker/test/fasttest/run.sh | 17 ++++++++++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docker/images.json b/docker/images.json index 45209fc775f..a88bff8961d 100644 --- a/docker/images.json +++ b/docker/images.json @@ -83,5 +83,10 @@ "docker/test/testflows/runner": { "name": "yandex/clickhouse-testflows-runner", "dependent": [] + }, + "docker/test/fasttest": { + "name": "yandex/clickhouse-fasttest", + "dependent": [] } + } diff --git a/docker/test/fasttest/Dockerfile b/docker/test/fasttest/Dockerfile index bb1e92cec49..b8653aac6c6 100644 --- a/docker/test/fasttest/Dockerfile +++ b/docker/test/fasttest/Dockerfile @@ -2,6 +2,8 @@ FROM ubuntu:19.10 ARG odbc_driver_url="https://github.com/ClickHouse/clickhouse-odbc/releases/download/v1.1.4.20200302/clickhouse-odbc-1.1.4-Linux.tar.gz" +ARG COMMIT_SHA='' +ARG PULL_REQUEST_NUMBER='' RUN apt-get --allow-unauthenticated update -y && apt-get install --yes wget gnupg RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - @@ -33,8 +35,6 @@ RUN apt-get --allow-unauthenticated update -y \ gperf \ rename \ build-essential \ - zookeeper \ - zookeeperd \ expect \ python \ python-lxml \ diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 0e04a419335..0cf04c19752 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -5,12 +5,22 @@ set -x -e ls -la git clone https://github.com/ClickHouse/ClickHouse.git | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/clone_log.txt + +if [ "$PULL_REQUEST_NUMBER" != "0"]; then + if git fetch origin "+refs/pull/$PULL_REQUEST_NUMBER/merge"; then + git checkout FETCH_HEAD + echo 'Clonned merge head' + else + git fetch + git checkout $COMMIT_SHA + fi +fi cd ClickHouse CLICKHOUSE_DIR=`pwd` git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0" +CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse @@ -35,6 +45,7 @@ mkdir -p /etc/clickhouse-server mkdir -p /etc/clickhouse-client mkdir -p /etc/clickhouse-server/config.d mkdir -p /etc/clickhouse-server/users.d +mkdir -p /var/log/clickhouse-server cp $CLICKHOUSE_DIR/programs/server/config.xml /etc/clickhouse-server/ cp $CLICKHOUSE_DIR/programs/server/users.xml /etc/clickhouse-server/ @@ -64,8 +75,6 @@ ln -s /usr/share/clickhouse-test/config/server.crt /etc/clickhouse-server/ ln -s /usr/share/clickhouse-test/config/dhparam.pem /etc/clickhouse-server/ ln -sf /usr/share/clickhouse-test/config/client_config.xml /etc/clickhouse-client/config.xml -service zookeeper start && sleep 5 - clickhouse-server --config /etc/clickhouse-server/config.xml --daemon until clickhouse-client --query "SELECT 1" @@ -74,3 +83,5 @@ do done clickhouse-test --testname --shard --zookeeper 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt + +mv /var/log/clickhouse-server/* /test_output From 58b91a1d0b1f3c733a63119385073cee0fc99b58 Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Wed, 8 Jul 2020 17:41:34 +0200 Subject: [PATCH 040/143] Updating tests to match new exit codes. --- tests/testflows/ldap/tests/server_config.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/testflows/ldap/tests/server_config.py b/tests/testflows/ldap/tests/server_config.py index eae36973c54..a4507d0b75e 100644 --- a/tests/testflows/ldap/tests/server_config.py +++ b/tests/testflows/ldap/tests/server_config.py @@ -28,7 +28,7 @@ def invalid_host(self): servers = {"foo": {"host": "foo", "port": "389", "enable_tls": "no"}} users = [{ "server": "foo", "username": "user1", "password": "user1", "login": True, - "exitcode": 17, "message": "DB::Exception: Can't contact LDAP server" + "exitcode": 19, "message": "DB::Exception: Can't contact LDAP server" }] login(servers, *users) @@ -75,7 +75,7 @@ def invalid_port(self): servers = {"openldap1": {"host": "openldap1", "port": "3890", "enable_tls": "no"}} users = [{ "server": "openldap1", "username": "user1", "password": "user1", "login": True, - "exitcode": 17, "message": "DB::Exception: Can't contact LDAP server." + "exitcode": 19, "message": "DB::Exception: Can't contact LDAP server." }] login(servers, *users) @@ -93,7 +93,7 @@ def invalid_auth_dn_prefix(self): }} users = [{ "server": "openldap1", "username": "user1", "password": "user1", "login": True, - "exitcode": 17, "message": "DB::Exception: Invalid DN syntax: invalid DN" + "exitcode": 19, "message": "DB::Exception: Invalid DN syntax: invalid DN" }] login(servers, *users) @@ -110,7 +110,7 @@ def invalid_auth_dn_suffix(self): }} users = [{ "server": "openldap1", "username": "user1", "password": "user1", "login": True, - "exitcode": 17, "message": "DB::Exception: Invalid DN syntax: invalid DN" + "exitcode": 19, "message": "DB::Exception: Invalid DN syntax: invalid DN" }] login(servers, *users) @@ -167,7 +167,7 @@ def empty_ca_cert_dir(self): }} users = [{ "server": "openldap2", "username": "user2", "password": "user2", "login": True, - "exitcode": 17, + "exitcode": 19, "message": "DB::Exception: Can't contact LDAP server: error:14000086:SSL routines::certificate verify failed (self signed certificate in certificate chain" }] login(servers, *users) @@ -187,7 +187,7 @@ def empty_ca_cert_file(self): }} users = [{ "server": "openldap2", "username": "user2", "password": "user2", "login": True, - "exitcode": 17, + "exitcode": 19, "message": "Received from localhost:9000. DB::Exception: Can't contact LDAP server: error:14000086:SSL routines::certificate verify failed (self signed certificate in certificate chain)" }] login(servers, *users) From 6378c79539a952afc5b3f1824682ff8172366b13 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 8 Jul 2020 19:02:19 +0300 Subject: [PATCH 041/143] Fix script --- docker/test/fasttest/Dockerfile | 4 ++-- docker/test/fasttest/run.sh | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/docker/test/fasttest/Dockerfile b/docker/test/fasttest/Dockerfile index b8653aac6c6..faa7c875275 100644 --- a/docker/test/fasttest/Dockerfile +++ b/docker/test/fasttest/Dockerfile @@ -2,8 +2,8 @@ FROM ubuntu:19.10 ARG odbc_driver_url="https://github.com/ClickHouse/clickhouse-odbc/releases/download/v1.1.4.20200302/clickhouse-odbc-1.1.4-Linux.tar.gz" -ARG COMMIT_SHA='' -ARG PULL_REQUEST_NUMBER='' +ENV COMMIT_SHA='' +ENV PULL_REQUEST_NUMBER='' RUN apt-get --allow-unauthenticated update -y && apt-get install --yes wget gnupg RUN wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 0cf04c19752..507b391d238 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -5,18 +5,26 @@ set -x -e ls -la git clone https://github.com/ClickHouse/ClickHouse.git | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/clone_log.txt +cd ClickHouse +CLICKHOUSE_DIR=`pwd` -if [ "$PULL_REQUEST_NUMBER" != "0"]; then + +if [ "$PULL_REQUEST_NUMBER" != "0" ]; then if git fetch origin "+refs/pull/$PULL_REQUEST_NUMBER/merge"; then git checkout FETCH_HEAD echo 'Clonned merge head' else git fetch git checkout $COMMIT_SHA + echo 'Checked out to commit' + fi +else + if [ "$COMMIT_SHA" != "" ]; then + git checkout $COMMIT_SHA fi fi -cd ClickHouse -CLICKHOUSE_DIR=`pwd` + + git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt From e0ff6bd6d745e82d124659fb931a40a8aadf5be9 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 8 Jul 2020 19:59:47 +0300 Subject: [PATCH 042/143] Less libraries to build --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 507b391d238..cf439d0f6b1 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -28,7 +28,7 @@ fi git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0" +CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_EMBEDDED_COMPILER=0" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse From ba1fbc55bea39580c0b33020e76115297fb9dfb7 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Thu, 9 Jul 2020 15:06:05 +0400 Subject: [PATCH 043/143] Fix the test: auth_params is a JSON object --- tests/integration/test_create_user_and_login/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_create_user_and_login/test.py b/tests/integration/test_create_user_and_login/test.py index 392a4ef98ee..18c894ed3d3 100644 --- a/tests/integration/test_create_user_and_login/test.py +++ b/tests/integration/test_create_user_and_login/test.py @@ -145,8 +145,8 @@ def test_introspection(): assert expected_access2 in instance.query("SHOW ACCESS") assert instance.query("SELECT name, storage, auth_type, auth_params, host_ip, host_names, host_names_regexp, host_names_like, default_roles_all, default_roles_list, default_roles_except from system.users WHERE name IN ('A', 'B') ORDER BY name") ==\ - TSV([[ "A", "disk", "no_password", "[]", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ], - [ "B", "disk", "no_password", "[]", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ]]) + TSV([[ "A", "disk", "no_password", "{}", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ], + [ "B", "disk", "no_password", "{}", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ]]) assert instance.query("SELECT * from system.grants WHERE user_name IN ('A', 'B') ORDER BY user_name, access_type, grant_option") ==\ TSV([[ "A", "\N", "SELECT", "test", "table", "\N", 0, 0 ], From 51aaa8800d6de8c03b083ac4ff4a3efc72f2ff30 Mon Sep 17 00:00:00 2001 From: alesapin Date: Thu, 9 Jul 2020 18:34:19 +0300 Subject: [PATCH 044/143] Don't skip libs --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index cf439d0f6b1..871c180dfee 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -28,7 +28,7 @@ fi git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_EMBEDDED_COMPILER=0" +#CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_EMBEDDED_COMPILER=0" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse From 0d5c747b86838c8a48646e5d4ad47f95f2d270db Mon Sep 17 00:00:00 2001 From: alesapin Date: Thu, 9 Jul 2020 21:59:32 +0300 Subject: [PATCH 045/143] Return strange line from clickhouse-test --- tests/clickhouse-test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/clickhouse-test b/tests/clickhouse-test index 98e00665230..07fe681c2c8 100755 --- a/tests/clickhouse-test +++ b/tests/clickhouse-test @@ -479,7 +479,7 @@ def main(args): # Keep same default values as in queries/shell_config.sh os.environ.setdefault("CLICKHOUSE_BINARY", args.binary) - os.environ.setdefault("CLICKHOUSE_CLIENT", args.client) + #os.environ.setdefault("CLICKHOUSE_CLIENT", args.client) os.environ.setdefault("CLICKHOUSE_CONFIG", args.configserver) if args.configclient: os.environ.setdefault("CLICKHOUSE_CONFIG_CLIENT", args.configclient) From a012ae3a70a3c2dbdca6e02c3eb6ad87773fceec Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Thu, 9 Jul 2020 22:01:53 +0200 Subject: [PATCH 046/143] * Updating exitcodes in server_config.py. * Addintion positive check when user password in LDAP changes. --- tests/testflows/ldap/tests/authentications.py | 4 ++++ tests/testflows/ldap/tests/server_config.py | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/testflows/ldap/tests/authentications.py b/tests/testflows/ldap/tests/authentications.py index ca152fb0409..4b054fb694e 100644 --- a/tests/testflows/ldap/tests/authentications.py +++ b/tests/testflows/ldap/tests/authentications.py @@ -165,6 +165,10 @@ def login_after_user_password_changed_in_ldap(self, server): exitcode=4, message=f"DB::Exception: {user['cn']}: Authentication failed: password is incorrect or there is no user with such name" ) + + with And("when I try to login with the new password it should work"): + login_and_execute_query(username=user["cn"], password="newpassword") + finally: with Finally("I make sure LDAP user is deleted"): if user is not None: diff --git a/tests/testflows/ldap/tests/server_config.py b/tests/testflows/ldap/tests/server_config.py index a4507d0b75e..f3d03434afe 100644 --- a/tests/testflows/ldap/tests/server_config.py +++ b/tests/testflows/ldap/tests/server_config.py @@ -28,7 +28,7 @@ def invalid_host(self): servers = {"foo": {"host": "foo", "port": "389", "enable_tls": "no"}} users = [{ "server": "foo", "username": "user1", "password": "user1", "login": True, - "exitcode": 19, "message": "DB::Exception: Can't contact LDAP server" + "exitcode": 20, "message": "DB::Exception: Can't contact LDAP server" }] login(servers, *users) @@ -75,7 +75,7 @@ def invalid_port(self): servers = {"openldap1": {"host": "openldap1", "port": "3890", "enable_tls": "no"}} users = [{ "server": "openldap1", "username": "user1", "password": "user1", "login": True, - "exitcode": 19, "message": "DB::Exception: Can't contact LDAP server." + "exitcode": 20, "message": "DB::Exception: Can't contact LDAP server." }] login(servers, *users) @@ -93,7 +93,7 @@ def invalid_auth_dn_prefix(self): }} users = [{ "server": "openldap1", "username": "user1", "password": "user1", "login": True, - "exitcode": 19, "message": "DB::Exception: Invalid DN syntax: invalid DN" + "exitcode": 20, "message": "DB::Exception: Invalid DN syntax: invalid DN" }] login(servers, *users) @@ -110,7 +110,7 @@ def invalid_auth_dn_suffix(self): }} users = [{ "server": "openldap1", "username": "user1", "password": "user1", "login": True, - "exitcode": 19, "message": "DB::Exception: Invalid DN syntax: invalid DN" + "exitcode": 20, "message": "DB::Exception: Invalid DN syntax: invalid DN" }] login(servers, *users) @@ -167,7 +167,7 @@ def empty_ca_cert_dir(self): }} users = [{ "server": "openldap2", "username": "user2", "password": "user2", "login": True, - "exitcode": 19, + "exitcode": 20, "message": "DB::Exception: Can't contact LDAP server: error:14000086:SSL routines::certificate verify failed (self signed certificate in certificate chain" }] login(servers, *users) @@ -187,7 +187,7 @@ def empty_ca_cert_file(self): }} users = [{ "server": "openldap2", "username": "user2", "password": "user2", "login": True, - "exitcode": 19, + "exitcode": 20, "message": "Received from localhost:9000. DB::Exception: Can't contact LDAP server: error:14000086:SSL routines::certificate verify failed (self signed certificate in certificate chain)" }] login(servers, *users) From 4ab5edadb72fb953f6948436e9d79b38805b1f54 Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 12:47:50 +0300 Subject: [PATCH 047/143] Less libraries --- cmake/find/amqpcpp.cmake | 3 ++- docker/test/fasttest/run.sh | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/find/amqpcpp.cmake b/cmake/find/amqpcpp.cmake index 0868e76c28a..faf10c1caef 100644 --- a/cmake/find/amqpcpp.cmake +++ b/cmake/find/amqpcpp.cmake @@ -1,4 +1,5 @@ -SET(ENABLE_AMQPCPP ${ENABLE_LIBRARIES}) +option(ENABLE_AMQPCPP "Enable AMQPCPP" ${ENABLE_LIBRARIES}) + if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/AMQP-CPP/CMakeLists.txt") message (WARNING "submodule contrib/AMQP-CPP is missing. to fix try run: \n git submodule update --init --recursive") set (ENABLE_AMQPCPP 0) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 871c180dfee..4c61c3fafc2 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -25,10 +25,9 @@ else fi - git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -#CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_EMBEDDED_COMPILER=0" +CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_UNWIND=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_REDIS=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_ODBC=0 -D ENABLE_MYSQL=0 -D ENABLE_SSL=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_CASSANDRA=0 -D ENABLE_PARQUET=0 -D ENABLE_AVRO=0 -D ENABLE_EMBEDDED_COMPILER=0" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse From 8688a1f5d005702fe9cc9acfb3590e8658a45957 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Fri, 10 Jul 2020 15:59:48 +0400 Subject: [PATCH 048/143] Recreate ExternalAuthenticators (LDAP) on config update --- programs/server/Server.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/programs/server/Server.cpp b/programs/server/Server.cpp index 626315d5cdb..c3b17824151 100644 --- a/programs/server/Server.cpp +++ b/programs/server/Server.cpp @@ -543,6 +543,7 @@ int Server::main(const std::vector & /*args*/) //buildLoggers(*config, logger()); global_context->setClustersConfig(config); global_context->setMacros(std::make_unique(*config, "macros")); + global_context->setExternalAuthenticatorsConfig(*config); /// Setup protection to avoid accidental DROP for big tables (that are greater than 50 GB by default) if (config->has("max_table_size_to_drop")) @@ -594,9 +595,6 @@ int Server::main(const std::vector & /*args*/) if (!access_control_local_path.empty()) global_context->getAccessControlManager().setLocalDirectory(access_control_local_path); - /// Sets external authenticators config (LDAP). - global_context->setExternalAuthenticatorsConfig(config()); - /// Limit on total number of concurrently executed queries. global_context->getProcessList().setMaxSize(config().getInt("max_concurrent_queries", 0)); From ce96262a2c91d38bd1514cfb85eeafa3128591dc Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 16:21:58 +0300 Subject: [PATCH 049/143] Update run.sh --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 4c61c3fafc2..adedc191e1c 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -27,7 +27,7 @@ fi git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_UNWIND=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_REDIS=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_ODBC=0 -D ENABLE_MYSQL=0 -D ENABLE_SSL=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_CASSANDRA=0 -D ENABLE_PARQUET=0 -D ENABLE_AVRO=0 -D ENABLE_EMBEDDED_COMPILER=0" +export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_UNWIND=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_REDIS=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_ODBC=0 -D ENABLE_MYSQL=0 -D ENABLE_SSL=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_CASSANDRA=0 -D ENABLE_PARQUET=0 -D ENABLE_AVRO=0 -D ENABLE_EMBEDDED_COMPILER=0" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse From 57d03bfbc0a5bc244987a1dfeadcaf85234cb958 Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 18:45:37 +0300 Subject: [PATCH 050/143] Disable secure ports --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index adedc191e1c..211d01883b2 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -74,7 +74,7 @@ ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-s ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/ ln -s /usr/share/clickhouse-test/config/macros.xml /etc/clickhouse-server/config.d/ ln -s /usr/share/clickhouse-test/config/disks.xml /etc/clickhouse-server/config.d/ -ln -s /usr/share/clickhouse-test/config/secure_ports.xml /etc/clickhouse-server/config.d/ +#ln -s /usr/share/clickhouse-test/config/secure_ports.xml /etc/clickhouse-server/config.d/ ln -s /usr/share/clickhouse-test/config/clusters.xml /etc/clickhouse-server/config.d/ ln -s /usr/share/clickhouse-test/config/graphite.xml /etc/clickhouse-server/config.d/ ln -s /usr/share/clickhouse-test/config/server.key /etc/clickhouse-server/ From 0b1a1867a69c5517200bbfe789b662310bd87e8e Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 20:21:24 +0300 Subject: [PATCH 051/143] Less dependencies --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 211d01883b2..c19598e92e2 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -27,7 +27,7 @@ fi git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_UNWIND=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_REDIS=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_ODBC=0 -D ENABLE_MYSQL=0 -D ENABLE_SSL=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_CASSANDRA=0 -D ENABLE_PARQUET=0 -D ENABLE_AVRO=0 -D ENABLE_EMBEDDED_COMPILER=0" +export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_UNWIND=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_REDIS=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_ODBC=0 -D ENABLE_MYSQL=0 -D ENABLE_SSL=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_CASSANDRA=0 -D ENABLE_PARQUET=0 -D ENABLE_AVRO=0 -D ENABLE_EMBEDDED_COMPILER=0 -D ENABLE_PROTOBUF=0 -D ENABLE_H3=0 -DENABLE_TESTS=0" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse From b70c3b607f8756d6a4db8c0aebdf963a3f4290d8 Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 20:44:29 +0300 Subject: [PATCH 052/143] No long tests --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index c19598e92e2..b3caa50dd06 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -89,6 +89,6 @@ do sleep 0.1 done -clickhouse-test --testname --shard --zookeeper 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt +clickhouse-test --no-long --testname --shard --zookeeper 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt mv /var/log/clickhouse-server/* /test_output From df176c633e1e6a1b27ffc75af4db3909ee413690 Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 21:27:10 +0300 Subject: [PATCH 053/143] Disable msgpack --- docker/test/fasttest/run.sh | 2 +- src/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index b3caa50dd06..b2ec015e1f8 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -27,7 +27,7 @@ fi git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -D ENABLE_CAPNP=0 -D ENABLE_RDKAFKA=0 -D ENABLE_UNWIND=0 -D ENABLE_ICU=0 -D ENABLE_POCO_MONGODB=0 -D ENABLE_POCO_REDIS=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_ODBC=0 -D ENABLE_MYSQL=0 -D ENABLE_SSL=0 -D ENABLE_POCO_NETSSL=0 -D ENABLE_CASSANDRA=0 -D ENABLE_PARQUET=0 -D ENABLE_AVRO=0 -D ENABLE_EMBEDDED_COMPILER=0 -D ENABLE_PROTOBUF=0 -D ENABLE_H3=0 -DENABLE_TESTS=0" +export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -DENABLE_CAPNP=0 -DENABLE_RDKAFKA=0 -DENABLE_UNWIND=0 -DENABLE_ICU=0 -DENABLE_POCO_MONGODB=0 -DENABLE_POCO_REDIS=0 -DENABLE_POCO_NETSSL=0 -DENABLE_ODBC=0 -DENABLE_MYSQL=0 -DENABLE_SSL=0 -DENABLE_POCO_NETSSL=0 -DENABLE_CASSANDRA=0 -DENABLE_PARQUET=0 -DENABLE_AVRO=0 -DENABLE_EMBEDDED_COMPILER=0 -DENABLE_PROTOBUF=0 -DENABLE_H3=0 -DENABLE_TESTS=0 -DENABLE_UTILS=0 -DENABLE_ODBC=0 -DUSE_INTERNAL_LIBGSASL_LIBRARY=0 -DENABLE_THINLTO=0 -DUSE_INTERNAL_MSGPACK_LIBRARY=0 -DENABLE_LDAP=0 -DUSE_SNAPPY=0 -DUSE_INTERNAL_GTEST_LIBRARY=0" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index be5d3ba836d..1a3cafb5d7f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -370,7 +370,9 @@ endif() target_include_directories (clickhouse_common_io SYSTEM BEFORE PUBLIC ${DOUBLE_CONVERSION_INCLUDE_DIR}) -target_include_directories (clickhouse_common_io SYSTEM BEFORE PUBLIC ${MSGPACK_INCLUDE_DIR}) +if (USE_INTERNAL_MSGPACK_LIBRARY) + target_include_directories (clickhouse_common_io SYSTEM BEFORE PUBLIC ${MSGPACK_INCLUDE_DIR}) +endif() if (USE_ORC) dbms_target_link_libraries(PUBLIC ${ORC_LIBRARIES}) From a9824fd65022fdc7357dc0f9d3bcb25b2859cf13 Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 22:08:18 +0300 Subject: [PATCH 054/143] Better cmake and less libraries --- cmake/find/gtest.cmake | 6 ++++++ cmake/find/libgsasl.cmake | 6 ++++++ cmake/find/msgpack.cmake | 12 +++++++++++- docker/test/fasttest/run.sh | 2 +- src/CMakeLists.txt | 2 +- src/Formats/config_formats.h.in | 2 ++ .../Formats/Impl/MsgPackRowInputFormat.cpp | 7 ++++++- src/Processors/Formats/Impl/MsgPackRowInputFormat.h | 7 +++++++ .../Formats/Impl/MsgPackRowOutputFormat.cpp | 5 +++++ src/Processors/Formats/Impl/MsgPackRowOutputFormat.h | 7 +++++++ 10 files changed, 52 insertions(+), 4 deletions(-) diff --git a/cmake/find/gtest.cmake b/cmake/find/gtest.cmake index 82ae0f8e229..b41c4cc0af8 100644 --- a/cmake/find/gtest.cmake +++ b/cmake/find/gtest.cmake @@ -1,3 +1,7 @@ +option (ENABLE_GTEST_LIBRARY "Enable gtest library" ${ENABLE_LIBRARIES}) + +if (ENABLE_GTEST_LIBRARY) + option (USE_INTERNAL_GTEST_LIBRARY "Set to FALSE to use system Google Test instead of bundled" ${NOT_UNBUNDLED}) if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/googletest/googletest/CMakeLists.txt") @@ -28,4 +32,6 @@ if((GTEST_INCLUDE_DIRS AND GTEST_BOTH_LIBRARIES) OR GTEST_SRC_DIR) set(USE_GTEST 1) endif() +endif() + message (STATUS "Using gtest=${USE_GTEST}: ${GTEST_INCLUDE_DIRS} : ${GTEST_BOTH_LIBRARIES} : ${GTEST_SRC_DIR}") diff --git a/cmake/find/libgsasl.cmake b/cmake/find/libgsasl.cmake index 801b63899da..e9c45a09010 100644 --- a/cmake/find/libgsasl.cmake +++ b/cmake/find/libgsasl.cmake @@ -1,3 +1,7 @@ +option(ENABLE_GSASL_LIBRARY "Enable gsasl library" ${ENABLE_LIBRARIES}) + +if (ENABLE_GSASL_LIBRARY) + option (USE_INTERNAL_LIBGSASL_LIBRARY "Set to FALSE to use system libgsasl library instead of bundled" ${NOT_UNBUNDLED}) if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/libgsasl/src/gsasl.h") @@ -24,4 +28,6 @@ if(LIBGSASL_LIBRARY AND LIBGSASL_INCLUDE_DIR) set (USE_LIBGSASL 1) endif() +endif() + message (STATUS "Using libgsasl=${USE_LIBGSASL}: ${LIBGSASL_INCLUDE_DIR} : ${LIBGSASL_LIBRARY}") diff --git a/cmake/find/msgpack.cmake b/cmake/find/msgpack.cmake index 46344fc162f..db7dbea42db 100644 --- a/cmake/find/msgpack.cmake +++ b/cmake/find/msgpack.cmake @@ -1,3 +1,7 @@ +option (ENABLE_MSGPACK "Enable msgpack library" ${ENABLE_LIBRARIES}) + +if (ENABLE_MSGPACK) + option (USE_INTERNAL_MSGPACK_LIBRARY "Set to FALSE to use system msgpack library instead of bundled" ${NOT_UNBUNDLED}) if (USE_INTERNAL_MSGPACK_LIBRARY) @@ -14,4 +18,10 @@ else() find_path(MSGPACK_INCLUDE_DIR NAMES msgpack.hpp PATHS ${MSGPACK_INCLUDE_PATHS}) endif() -message(STATUS "Using msgpack: ${MSGPACK_INCLUDE_DIR}") +if (MSG_PACK_INCLUDE_DIR) + set(USE_MSGPACK 1) +endif() + +endif() + +message(STATUS "Using msgpack=${USE_MSGPACK}: ${MSGPACK_INCLUDE_DIR}") diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index b2ec015e1f8..ef158bfbdfa 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -27,7 +27,7 @@ fi git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -DENABLE_CAPNP=0 -DENABLE_RDKAFKA=0 -DENABLE_UNWIND=0 -DENABLE_ICU=0 -DENABLE_POCO_MONGODB=0 -DENABLE_POCO_REDIS=0 -DENABLE_POCO_NETSSL=0 -DENABLE_ODBC=0 -DENABLE_MYSQL=0 -DENABLE_SSL=0 -DENABLE_POCO_NETSSL=0 -DENABLE_CASSANDRA=0 -DENABLE_PARQUET=0 -DENABLE_AVRO=0 -DENABLE_EMBEDDED_COMPILER=0 -DENABLE_PROTOBUF=0 -DENABLE_H3=0 -DENABLE_TESTS=0 -DENABLE_UTILS=0 -DENABLE_ODBC=0 -DUSE_INTERNAL_LIBGSASL_LIBRARY=0 -DENABLE_THINLTO=0 -DUSE_INTERNAL_MSGPACK_LIBRARY=0 -DENABLE_LDAP=0 -DUSE_SNAPPY=0 -DUSE_INTERNAL_GTEST_LIBRARY=0" +export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -DENABLE_CAPNP=0 -DENABLE_RDKAFKA=0 -DENABLE_ICU=0 -DENABLE_POCO_NETSSL=0 -DENABLE_ODBC=0 -DENABLE_MYSQL=0 -DENABLE_SSL=0 -DENABLE_POCO_NETSSL=0 -DENABLE_CASSANDRA=0 -DENABLE_PARQUET=0 -DENABLE_AVRO=0 -DENABLE_EMBEDDED_COMPILER=0 -DENABLE_PROTOBUF=0 -DENABLE_H3=0 -DENABLE_TESTS=0 -DENABLE_UTILS=0 -DENABLE_ODBC=0 -DENABLE_GSASL_LIBRARY=0 -DENABLE_THINLTO=0 -DENABLE_MSGPACK=0 -DENABLE_LDAP=0 -DUSE_SNAPPY=0" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1a3cafb5d7f..ecc2bca8a6e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -370,7 +370,7 @@ endif() target_include_directories (clickhouse_common_io SYSTEM BEFORE PUBLIC ${DOUBLE_CONVERSION_INCLUDE_DIR}) -if (USE_INTERNAL_MSGPACK_LIBRARY) +if (USE_MSGPACK) target_include_directories (clickhouse_common_io SYSTEM BEFORE PUBLIC ${MSGPACK_INCLUDE_DIR}) endif() diff --git a/src/Formats/config_formats.h.in b/src/Formats/config_formats.h.in index 77556b91c0c..f6497b4830b 100644 --- a/src/Formats/config_formats.h.in +++ b/src/Formats/config_formats.h.in @@ -9,3 +9,5 @@ #cmakedefine01 USE_ORC #cmakedefine01 USE_ARROW #cmakedefine01 USE_PROTOBUF +#cmakedefine01 USE_MSGPACK + diff --git a/src/Processors/Formats/Impl/MsgPackRowInputFormat.cpp b/src/Processors/Formats/Impl/MsgPackRowInputFormat.cpp index 4581a82f06e..718d90a22e9 100644 --- a/src/Processors/Formats/Impl/MsgPackRowInputFormat.cpp +++ b/src/Processors/Formats/Impl/MsgPackRowInputFormat.cpp @@ -1,5 +1,8 @@ -#include #include + +#if USE_MSGPACK + +#include #include #include @@ -209,3 +212,5 @@ void registerInputFormatProcessorMsgPack(FormatFactory & factory) } } + +#endif diff --git a/src/Processors/Formats/Impl/MsgPackRowInputFormat.h b/src/Processors/Formats/Impl/MsgPackRowInputFormat.h index 454d42fae3d..add5c516771 100644 --- a/src/Processors/Formats/Impl/MsgPackRowInputFormat.h +++ b/src/Processors/Formats/Impl/MsgPackRowInputFormat.h @@ -1,5 +1,10 @@ #pragma once +#include "config_formats.h" +#include "config_core.h" + +#if USE_MSGPACK + #include #include #include @@ -63,3 +68,5 @@ private: }; } + +#endif diff --git a/src/Processors/Formats/Impl/MsgPackRowOutputFormat.cpp b/src/Processors/Formats/Impl/MsgPackRowOutputFormat.cpp index cef7b001505..b9afcbc0e76 100644 --- a/src/Processors/Formats/Impl/MsgPackRowOutputFormat.cpp +++ b/src/Processors/Formats/Impl/MsgPackRowOutputFormat.cpp @@ -1,4 +1,7 @@ #include + +#if USE_MSGPACK + #include #include @@ -157,3 +160,5 @@ void registerOutputFormatProcessorMsgPack(FormatFactory & factory) } } + +#endif diff --git a/src/Processors/Formats/Impl/MsgPackRowOutputFormat.h b/src/Processors/Formats/Impl/MsgPackRowOutputFormat.h index 351920eb7c8..401fe492f56 100644 --- a/src/Processors/Formats/Impl/MsgPackRowOutputFormat.h +++ b/src/Processors/Formats/Impl/MsgPackRowOutputFormat.h @@ -1,5 +1,10 @@ #pragma once +#include "config_formats.h" +#include "config_core.h" + +#if USE_MSGPACK + #include #include #include @@ -26,3 +31,5 @@ private: }; } + +#endif From 69d6ad0a627c08397fcf8cbcb2b7caf5aaf08776 Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 22:12:25 +0300 Subject: [PATCH 055/143] Disable bunch of tests --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index ef158bfbdfa..d9ae8cbe6ac 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -89,6 +89,6 @@ do sleep 0.1 done -clickhouse-test --no-long --testname --shard --zookeeper 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt +clickhouse-test --no-long --testname --shard --zookeeper --skip parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt mv /var/log/clickhouse-server/* /test_output From d2fcbe1f4ec4625e47c498d756435dfbd1a7afe6 Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 22:27:12 +0300 Subject: [PATCH 056/143] Fix build --- docker/test/fasttest/run.sh | 2 +- .../Formats/Impl/MsgPackRowInputFormat.cpp | 10 ++++++++++ .../Formats/Impl/MsgPackRowOutputFormat.cpp | 12 ++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index d9ae8cbe6ac..093d8a8314f 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -27,7 +27,7 @@ fi git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -DENABLE_CAPNP=0 -DENABLE_RDKAFKA=0 -DENABLE_ICU=0 -DENABLE_POCO_NETSSL=0 -DENABLE_ODBC=0 -DENABLE_MYSQL=0 -DENABLE_SSL=0 -DENABLE_POCO_NETSSL=0 -DENABLE_CASSANDRA=0 -DENABLE_PARQUET=0 -DENABLE_AVRO=0 -DENABLE_EMBEDDED_COMPILER=0 -DENABLE_PROTOBUF=0 -DENABLE_H3=0 -DENABLE_TESTS=0 -DENABLE_UTILS=0 -DENABLE_ODBC=0 -DENABLE_GSASL_LIBRARY=0 -DENABLE_THINLTO=0 -DENABLE_MSGPACK=0 -DENABLE_LDAP=0 -DUSE_SNAPPY=0" +export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -DENABLE_CAPNP=0 -DENABLE_RDKAFKA=0 -DENABLE_ICU=0 -DENABLE_POCO_NETSSL=0 -DENABLE_ODBC=0 -DENABLE_MYSQL=0 -DENABLE_SSL=0 -DENABLE_POCO_NETSSL=0 -DENABLE_CASSANDRA=0 -DENABLE_PARQUET=0 -DENABLE_AVRO=0 -DENABLE_EMBEDDED_COMPILER=0 -DENABLE_PROTOBUF=0 -DENABLE_H3=0 -DENABLE_TESTS=0 -DENABLE_UTILS=0 -DENABLE_ODBC=0 -DENABLE_GSASL_LIBRARY=0 -DENABLE_THINLTO=0 -DENABLE_MSGPACK=0 -DENABLE_LDAP=0 -DUSE_SNAPPY=0 -DENABLE_HYPERSCAN=0" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse diff --git a/src/Processors/Formats/Impl/MsgPackRowInputFormat.cpp b/src/Processors/Formats/Impl/MsgPackRowInputFormat.cpp index 718d90a22e9..6eb9d1d037c 100644 --- a/src/Processors/Formats/Impl/MsgPackRowInputFormat.cpp +++ b/src/Processors/Formats/Impl/MsgPackRowInputFormat.cpp @@ -213,4 +213,14 @@ void registerInputFormatProcessorMsgPack(FormatFactory & factory) } +#else + +namespace DB +{ +class FormatFactory; +void registerInputFormatProcessorMsgPack(FormatFactory &) +{ +} +} + #endif diff --git a/src/Processors/Formats/Impl/MsgPackRowOutputFormat.cpp b/src/Processors/Formats/Impl/MsgPackRowOutputFormat.cpp index b9afcbc0e76..cc0a5f297ea 100644 --- a/src/Processors/Formats/Impl/MsgPackRowOutputFormat.cpp +++ b/src/Processors/Formats/Impl/MsgPackRowOutputFormat.cpp @@ -147,8 +147,10 @@ void MsgPackRowOutputFormat::write(const Columns & columns, size_t row_num) } } + void registerOutputFormatProcessorMsgPack(FormatFactory & factory) { + factory.registerOutputFormatProcessor("MsgPack", []( WriteBuffer & buf, const Block & sample, @@ -161,4 +163,14 @@ void registerOutputFormatProcessorMsgPack(FormatFactory & factory) } +#else + +namespace DB +{ +class FormatFactory; +void registerOutputFormatProcessorMsgPack(FormatFactory &) +{ +} +} + #endif From d69f925c30a4a1f54b5441ed9f12882a64ed6da6 Mon Sep 17 00:00:00 2001 From: alesapin Date: Fri, 10 Jul 2020 22:28:21 +0300 Subject: [PATCH 057/143] Fix build --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 093d8a8314f..fe44234fe64 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -42,7 +42,7 @@ mkdir build cd build CLICKHOUSE_BUILD_DIR=`pwd` cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_CXX_COMPILER=clang++-10 -DCMAKE_C_COMPILER=clang-10 $CMAKE_LIBS_CONFIG | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/cmake_log.txt -ninja | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/build_log.txt +ninja clickhouse-bundle | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/build_log.txt ninja install | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/install_log.txt From af98e74afd83b28ef6668fb2789554325c300d1f Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Sat, 11 Jul 2020 02:42:48 +0400 Subject: [PATCH 058/143] Gracefully handle the case when ExternalAuthenticators instance is not created (yet) --- src/Access/AccessControlManager.cpp | 4 ++-- src/Access/AccessControlManager.h | 2 +- src/Access/Authentication.cpp | 8 ++++++-- src/Access/Authentication.h | 2 +- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Access/AccessControlManager.cpp b/src/Access/AccessControlManager.cpp index 6a5529e65de..2f900374a46 100644 --- a/src/Access/AccessControlManager.cpp +++ b/src/Access/AccessControlManager.cpp @@ -170,9 +170,9 @@ std::shared_ptr AccessControlManager::getProfileSettings( return settings_profiles_cache->getProfileSettings(profile_name); } -const ExternalAuthenticators & AccessControlManager::getExternalAuthenticators() const +const ExternalAuthenticators * AccessControlManager::getExternalAuthenticators() const { - return *external_authenticators; + return external_authenticators.get(); } } diff --git a/src/Access/AccessControlManager.h b/src/Access/AccessControlManager.h index 467b7471423..7089ee50a85 100644 --- a/src/Access/AccessControlManager.h +++ b/src/Access/AccessControlManager.h @@ -87,7 +87,7 @@ public: std::shared_ptr getProfileSettings(const String & profile_name) const; - const ExternalAuthenticators & getExternalAuthenticators() const; + const ExternalAuthenticators * getExternalAuthenticators() const; private: class ContextAccessCache; diff --git a/src/Access/Authentication.cpp b/src/Access/Authentication.cpp index 970cb89ac10..4338e53c08a 100644 --- a/src/Access/Authentication.cpp +++ b/src/Access/Authentication.cpp @@ -49,7 +49,7 @@ Authentication::Digest Authentication::getPasswordDoubleSHA1() const } -bool Authentication::isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators & external_authenticators) const +bool Authentication::isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators * external_authenticators) const { switch (type) { @@ -82,9 +82,13 @@ bool Authentication::isCorrectPassword(const String & password_, const String & case LDAP_SERVER: { - auto ldap_server_params = external_authenticators.getLDAPServerParams(server_name); + if (!external_authenticators) + throw Exception("External authenticators are not configured", ErrorCodes::BAD_ARGUMENTS); + + auto ldap_server_params = external_authenticators->getLDAPServerParams(server_name); ldap_server_params.user = user_; ldap_server_params.password = password_; + LDAPSimpleAuthClient ldap_client(ldap_server_params); return ldap_client.check(); } diff --git a/src/Access/Authentication.h b/src/Access/Authentication.h index 35ff0fa1d32..6faf5a369eb 100644 --- a/src/Access/Authentication.h +++ b/src/Access/Authentication.h @@ -89,7 +89,7 @@ public: /// Checks if the provided password is correct. Returns false if not. /// User name and external authenticators' info are used only by some specific authentication type (e.g., LDAP_SERVER). - bool isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators & external_authenticators) const; + bool isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators * external_authenticators) const; friend bool operator ==(const Authentication & lhs, const Authentication & rhs) { return (lhs.type == rhs.type) && (lhs.password_hash == rhs.password_hash); } friend bool operator !=(const Authentication & lhs, const Authentication & rhs) { return !(lhs == rhs); } From 3e68368b59f9380b160242e819d5e4a5e14ad8e6 Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Sat, 11 Jul 2020 21:06:01 +0400 Subject: [PATCH 059/143] Refactor ExternalAuthenticators configuration process --- src/Access/AccessControlManager.cpp | 9 +++++---- src/Access/AccessControlManager.h | 2 +- src/Access/Authentication.cpp | 7 ++----- src/Access/Authentication.h | 2 +- src/Access/ExternalAuthenticators.cpp | 9 ++++++++- src/Access/ExternalAuthenticators.h | 5 +++-- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/Access/AccessControlManager.cpp b/src/Access/AccessControlManager.cpp index 2f900374a46..5966c1aff75 100644 --- a/src/Access/AccessControlManager.cpp +++ b/src/Access/AccessControlManager.cpp @@ -65,7 +65,8 @@ AccessControlManager::AccessControlManager() role_cache(std::make_unique(*this)), row_policy_cache(std::make_unique(*this)), quota_cache(std::make_unique(*this)), - settings_profiles_cache(std::make_unique(*this)) + settings_profiles_cache(std::make_unique(*this)), + external_authenticators(std::make_unique()) { } @@ -82,7 +83,7 @@ void AccessControlManager::setLocalDirectory(const String & directory_path) void AccessControlManager::setExternalAuthenticatorsConfig(const Poco::Util::AbstractConfiguration & config) { - external_authenticators = std::make_unique(config, getLogger()); + external_authenticators->setConfig(config, getLogger()); } @@ -170,9 +171,9 @@ std::shared_ptr AccessControlManager::getProfileSettings( return settings_profiles_cache->getProfileSettings(profile_name); } -const ExternalAuthenticators * AccessControlManager::getExternalAuthenticators() const +const ExternalAuthenticators & AccessControlManager::getExternalAuthenticators() const { - return external_authenticators.get(); + return *external_authenticators; } } diff --git a/src/Access/AccessControlManager.h b/src/Access/AccessControlManager.h index 7089ee50a85..467b7471423 100644 --- a/src/Access/AccessControlManager.h +++ b/src/Access/AccessControlManager.h @@ -87,7 +87,7 @@ public: std::shared_ptr getProfileSettings(const String & profile_name) const; - const ExternalAuthenticators * getExternalAuthenticators() const; + const ExternalAuthenticators & getExternalAuthenticators() const; private: class ContextAccessCache; diff --git a/src/Access/Authentication.cpp b/src/Access/Authentication.cpp index 4338e53c08a..d29e2f897e8 100644 --- a/src/Access/Authentication.cpp +++ b/src/Access/Authentication.cpp @@ -49,7 +49,7 @@ Authentication::Digest Authentication::getPasswordDoubleSHA1() const } -bool Authentication::isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators * external_authenticators) const +bool Authentication::isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators & external_authenticators) const { switch (type) { @@ -82,10 +82,7 @@ bool Authentication::isCorrectPassword(const String & password_, const String & case LDAP_SERVER: { - if (!external_authenticators) - throw Exception("External authenticators are not configured", ErrorCodes::BAD_ARGUMENTS); - - auto ldap_server_params = external_authenticators->getLDAPServerParams(server_name); + auto ldap_server_params = external_authenticators.getLDAPServerParams(server_name); ldap_server_params.user = user_; ldap_server_params.password = password_; diff --git a/src/Access/Authentication.h b/src/Access/Authentication.h index 6faf5a369eb..35ff0fa1d32 100644 --- a/src/Access/Authentication.h +++ b/src/Access/Authentication.h @@ -89,7 +89,7 @@ public: /// Checks if the provided password is correct. Returns false if not. /// User name and external authenticators' info are used only by some specific authentication type (e.g., LDAP_SERVER). - bool isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators * external_authenticators) const; + bool isCorrectPassword(const String & password_, const String & user_, const ExternalAuthenticators & external_authenticators) const; friend bool operator ==(const Authentication & lhs, const Authentication & rhs) { return (lhs.type == rhs.type) && (lhs.password_hash == rhs.password_hash); } friend bool operator !=(const Authentication & lhs, const Authentication & rhs) { return !(lhs == rhs); } diff --git a/src/Access/ExternalAuthenticators.cpp b/src/Access/ExternalAuthenticators.cpp index fcb7317a52d..4f4104214c3 100644 --- a/src/Access/ExternalAuthenticators.cpp +++ b/src/Access/ExternalAuthenticators.cpp @@ -150,8 +150,15 @@ void parseAndAddLDAPServers(ExternalAuthenticators & external_authenticators, co } -ExternalAuthenticators::ExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) +void ExternalAuthenticators::reset() { + std::scoped_lock lock(mutex); + ldap_server_params.clear(); +} + +void ExternalAuthenticators::setConfig(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log) { + std::scoped_lock lock(mutex); + reset(); parseAndAddLDAPServers(*this, config, log); } diff --git a/src/Access/ExternalAuthenticators.h b/src/Access/ExternalAuthenticators.h index 50d9e68f91f..54af87604a6 100644 --- a/src/Access/ExternalAuthenticators.h +++ b/src/Access/ExternalAuthenticators.h @@ -25,13 +25,14 @@ namespace DB class ExternalAuthenticators { public: - explicit ExternalAuthenticators(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log); + void reset(); + void setConfig(const Poco::Util::AbstractConfiguration & config, Poco::Logger * log); void setLDAPServerParams(const String & server, const LDAPServerParams & params); LDAPServerParams getLDAPServerParams(const String & server) const; private: - mutable std::mutex mutex; + mutable std::recursive_mutex mutex; std::map ldap_server_params; }; From 2a3a0d47b35ae7f9665cda609f1b4b44336d181a Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Sat, 11 Jul 2020 21:31:00 +0400 Subject: [PATCH 060/143] Style fix --- src/Access/ExternalAuthenticators.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Access/ExternalAuthenticators.cpp b/src/Access/ExternalAuthenticators.cpp index 4f4104214c3..a0c5fbf1a79 100644 --- a/src/Access/ExternalAuthenticators.cpp +++ b/src/Access/ExternalAuthenticators.cpp @@ -150,7 +150,8 @@ void parseAndAddLDAPServers(ExternalAuthenticators & external_authenticators, co } -void ExternalAuthenticators::reset() { +void ExternalAuthenticators::reset() +{ std::scoped_lock lock(mutex); ldap_server_params.clear(); } From d9d8d0242e448eda9f31c140e859835ed5cbfd84 Mon Sep 17 00:00:00 2001 From: Ivan Babrou Date: Tue, 7 Jul 2020 11:10:44 -0700 Subject: [PATCH 061/143] Optimize PK lookup for queries that match exact PK range Existing code that looks up marks that match the query has a pathological case, when most of the part does in fact match the query. The code works by recursively splitting a part into ranges and then discarding the ranges that definitely do not match the query, based on primary key. The problem is that it requires visiting every mark that matches the query, making the complexity of this sort of look up O(n). For queries that match exact range on the primary key, we can find both left and right parts of the range with O(log 2) complexity. This change implements exactly that. To engage this optimization, the query must: * Have a prefix list of the primary key. * Have only range or single set element constraints for columns. * Have only AND as a boolean operator. Consider a table with `(service, timestamp)` as the primary key. The following conditions will be optimized: * `service = 'foo'` * `service = 'foo' and timestamp >= now() - 3600` * `service in ('foo')` * `service in ('foo') and timestamp >= now() - 3600 and timestamp <= now` The following will fall back to previous lookup algorithm: * `timestamp >= now() - 3600` * `service in ('foo', 'bar') and timestamp >= now() - 3600` * `service = 'foo'` Note that the optimization won't engage when PK has a range expression followed by a point expression, since in that case the range is not continuous. Trace query logging provides the following messages types of messages, each representing a different kind of PK usage for a part: ``` Used optimized inclusion search over index for part 20200711_5710108_5710108_0 with 9 steps Used generic exclusion search over index for part 20200711_5710118_5710228_5 with 1495 steps Not using index on part 20200710_5710473_5710473_0 ``` Number of steps translates to computational complexity. Here's a comparison for before and after for a query over 24h of data: ``` Read 4562944 rows, 148.05 MiB in 45.19249672 sec., 100966 rows/sec., 3.28 MiB/sec. Read 4183040 rows, 135.78 MiB in 0.196279627 sec., 21311636 rows/sec., 691.75 MiB/sec. ``` This is especially useful for queries that read data in order and terminate early to return "last X things" matching a query. See #11564 for more thoughts on this. --- src/Storages/MergeTree/KeyCondition.cpp | 72 +++++++ src/Storages/MergeTree/KeyCondition.h | 2 + .../MergeTree/MergeTreeDataSelectExecutor.cpp | 194 +++++++++++++----- .../MergeTree/MergeTreeDataSelectExecutor.h | 4 +- 4 files changed, 214 insertions(+), 58 deletions(-) diff --git a/src/Storages/MergeTree/KeyCondition.cpp b/src/Storages/MergeTree/KeyCondition.cpp index 5905272d827..d08ae5dde44 100644 --- a/src/Storages/MergeTree/KeyCondition.cpp +++ b/src/Storages/MergeTree/KeyCondition.cpp @@ -1125,6 +1125,78 @@ std::optional KeyCondition::applyMonotonicFunctionsChainToRange( return key_range; } +// Returns whether the condition is one continuous range of the primary key, +// where every field is matched by range or a single element set. +// This allows to use a more efficient lookup with no extra reads. +bool KeyCondition::matchesExactContinuousRange() const +{ + // Not implemented yet. + if (hasMonotonicFunctionsChain()) + return false; + + enum Constraint + { + POINT, + RANGE, + UNKNOWN, + }; + + std::vector column_constraints(key_columns.size(), Constraint::UNKNOWN); + + for (const auto & element : rpn) + { + if (element.function == RPNElement::Function::FUNCTION_AND) + { + continue; + } + + if (element.function == RPNElement::Function::FUNCTION_IN_SET && element.set_index && element.set_index->size() == 1) + { + column_constraints[element.key_column] = Constraint::POINT; + continue; + } + + if (element.function == RPNElement::Function::FUNCTION_IN_RANGE) + { + if (element.range.left == element.range.right) + { + column_constraints[element.key_column] = Constraint::POINT; + } + if (column_constraints[element.key_column] != Constraint::POINT) + { + column_constraints[element.key_column] = Constraint::RANGE; + } + continue; + } + + return false; + } + + auto min_constraint = column_constraints[0]; + + if (min_constraint > Constraint::RANGE) + { + return false; + } + + for (size_t i = 1; i < key_columns.size(); ++i) + { + if (column_constraints[i] < min_constraint) + { + return false; + } + + if (column_constraints[i] == Constraint::RANGE && min_constraint == Constraint::RANGE) + { + return false; + } + + min_constraint = column_constraints[i]; + } + + return true; +} + BoolMask KeyCondition::checkInHyperrectangle( const std::vector & hyperrectangle, const DataTypes & data_types) const diff --git a/src/Storages/MergeTree/KeyCondition.h b/src/Storages/MergeTree/KeyCondition.h index 16197b9fa69..a37af2d677b 100644 --- a/src/Storages/MergeTree/KeyCondition.h +++ b/src/Storages/MergeTree/KeyCondition.h @@ -309,6 +309,8 @@ public: MonotonicFunctionsChain & functions, DataTypePtr current_type); + bool matchesExactContinuousRange() const; + private: /// The expression is stored as Reverse Polish Notation. struct RPNElement diff --git a/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp b/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp index 4eee1f1fccb..306bcd9000a 100644 --- a/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp +++ b/src/Storages/MergeTree/MergeTreeDataSelectExecutor.cpp @@ -1292,7 +1292,7 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange( const MergeTreeData::DataPartPtr & part, const StorageMetadataPtr & metadata_snapshot, const KeyCondition & key_condition, - const Settings & settings) + const Settings & settings) const { MarkRanges res; @@ -1306,14 +1306,73 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange( /// If index is not used. if (key_condition.alwaysUnknownOrTrue()) { + LOG_TRACE(log, "Not using index on part {}", part->name); + if (has_final_mark) res.push_back(MarkRange(0, marks_count - 1)); else res.push_back(MarkRange(0, marks_count)); + + return res; + } + + size_t used_key_size = key_condition.getMaxKeyColumn() + 1; + + std::function create_field_ref; + /// If there are no monotonic functions, there is no need to save block reference. + /// Passing explicit field to FieldRef allows to optimize ranges and shows better performance. + const auto & primary_key = metadata_snapshot->getPrimaryKey(); + if (key_condition.hasMonotonicFunctionsChain()) + { + auto index_block = std::make_shared(); + for (size_t i = 0; i < used_key_size; ++i) + index_block->insert({index[i], primary_key.data_types[i], primary_key.column_names[i]}); + + create_field_ref = [index_block](size_t row, size_t column, FieldRef & field) + { + field = {index_block.get(), row, column}; + }; } else { - size_t used_key_size = key_condition.getMaxKeyColumn() + 1; + create_field_ref = [&index](size_t row, size_t column, FieldRef & field) + { + index[column]->get(row, field); + }; + } + + /// NOTE Creating temporary Field objects to pass to KeyCondition. + std::vector index_left(used_key_size); + std::vector index_right(used_key_size); + + auto may_be_true_in_range = [&](MarkRange & range) + { + if (range.end == marks_count && !has_final_mark) + { + for (size_t i = 0; i < used_key_size; ++i) + create_field_ref(range.begin, i, index_left[i]); + + return key_condition.mayBeTrueAfter( + used_key_size, index_left.data(), primary_key.data_types); + } + + if (has_final_mark && range.end == marks_count) + range.end -= 1; /// Remove final empty mark. It's useful only for primary key condition. + + for (size_t i = 0; i < used_key_size; ++i) + { + create_field_ref(range.begin, i, index_left[i]); + create_field_ref(range.end, i, index_right[i]); + } + + return key_condition.mayBeTrueInRange( + used_key_size, index_left.data(), index_right.data(), primary_key.data_types); + }; + + if (!key_condition.matchesExactContinuousRange()) + { + // Do exclusion search, where we drop ranges that do not match + size_t min_marks_for_seek = roundRowsOrBytesToMarks( settings.merge_tree_min_rows_for_seek, settings.merge_tree_min_bytes_for_seek, @@ -1321,69 +1380,22 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange( part->index_granularity_info.index_granularity_bytes); /** There will always be disjoint suspicious segments on the stack, the leftmost one at the top (back). - * At each step, take the left segment and check if it fits. - * If fits, split it into smaller ones and put them on the stack. If not, discard it. - * If the segment is already of one mark length, add it to response and discard it. - */ + * At each step, take the left segment and check if it fits. + * If fits, split it into smaller ones and put them on the stack. If not, discard it. + * If the segment is already of one mark length, add it to response and discard it. + */ std::vector ranges_stack = { {0, marks_count} }; - std::function create_field_ref; - /// If there are no monotonic functions, there is no need to save block reference. - /// Passing explicit field to FieldRef allows to optimize ranges and shows better performance. - const auto & primary_key = metadata_snapshot->getPrimaryKey(); - if (key_condition.hasMonotonicFunctionsChain()) - { - auto index_block = std::make_shared(); - for (size_t i = 0; i < used_key_size; ++i) - index_block->insert({index[i], primary_key.data_types[i], primary_key.column_names[i]}); - - create_field_ref = [index_block](size_t row, size_t column, FieldRef & field) - { - field = {index_block.get(), row, column}; - }; - } - else - { - create_field_ref = [&index](size_t row, size_t column, FieldRef & field) - { - index[column]->get(row, field); - }; - } - - /// NOTE Creating temporary Field objects to pass to KeyCondition. - std::vector index_left(used_key_size); - std::vector index_right(used_key_size); + size_t steps = 0; while (!ranges_stack.empty()) { MarkRange range = ranges_stack.back(); ranges_stack.pop_back(); - bool may_be_true; - if (range.end == marks_count && !has_final_mark) - { - for (size_t i = 0; i < used_key_size; ++i) - create_field_ref(range.begin, i, index_left[i]); + steps++; - may_be_true = key_condition.mayBeTrueAfter( - used_key_size, index_left.data(), primary_key.data_types); - } - else - { - if (has_final_mark && range.end == marks_count) - range.end -= 1; /// Remove final empty mark. It's useful only for primary key condition. - - for (size_t i = 0; i < used_key_size; ++i) - { - create_field_ref(range.begin, i, index_left[i]); - create_field_ref(range.end, i, index_right[i]); - } - - may_be_true = key_condition.mayBeTrueInRange( - used_key_size, index_left.data(), index_right.data(), primary_key.data_types); - } - - if (!may_be_true) + if (!may_be_true_in_range(range)) continue; if (range.end == range.begin + 1) @@ -1406,6 +1418,76 @@ MarkRanges MergeTreeDataSelectExecutor::markRangesFromPKRange( ranges_stack.emplace_back(range.begin, end); } } + + LOG_TRACE(log, "Used generic exclusion search over index for part {} with {} steps", part->name, steps); + } + else + { + // Do inclusion search, where we only look for one range + + size_t steps = 0; + + auto find_leaf = [&](bool left) -> std::optional + { + std::vector stack = {}; + + MarkRange range = {0, marks_count}; + + steps++; + + if (may_be_true_in_range(range)) + stack.emplace_back(range.begin, range.end); + + while (!stack.empty()) + { + range = stack.back(); + stack.pop_back(); + + if (range.end == range.begin + 1) + { + if (left) + return range.begin; + else + return range.end; + } + else + { + std::vector check_order = {}; + + MarkRange left_range = {range.begin, (range.begin + range.end) / 2}; + MarkRange right_range = {(range.begin + range.end) / 2, range.end}; + + if (left) + { + check_order.emplace_back(left_range.begin, left_range.end); + check_order.emplace_back(right_range.begin, right_range.end); + } + else + { + check_order.emplace_back(right_range.begin, right_range.end); + check_order.emplace_back(left_range.begin, left_range.end); + } + + steps++; + + if (may_be_true_in_range(check_order[0])) + { + stack.emplace_back(check_order[0].begin, check_order[0].end); + continue; + } + + stack.emplace_back(check_order[1].begin, check_order[1].end); + } + } + + return std::nullopt; + }; + + auto left_leaf = find_leaf(true); + if (left_leaf) + res.emplace_back(left_leaf.value(), find_leaf(false).value()); + + LOG_TRACE(log, "Used optimized inclusion search over index for part {} with {} steps", part->name, steps); } return res; diff --git a/src/Storages/MergeTree/MergeTreeDataSelectExecutor.h b/src/Storages/MergeTree/MergeTreeDataSelectExecutor.h index 831b690ec62..52d00546a05 100644 --- a/src/Storages/MergeTree/MergeTreeDataSelectExecutor.h +++ b/src/Storages/MergeTree/MergeTreeDataSelectExecutor.h @@ -95,11 +95,11 @@ private: const KeyCondition & key_condition, const Settings & settings) const; - static MarkRanges markRangesFromPKRange( + MarkRanges markRangesFromPKRange( const MergeTreeData::DataPartPtr & part, const StorageMetadataPtr & metadata_snapshot, const KeyCondition & key_condition, - const Settings & settings); + const Settings & settings) const; MarkRanges filterMarksUsingIndex( MergeTreeIndexPtr index_helper, From a6a6f43422d671e4107ac4604b8f9b00ce90361a Mon Sep 17 00:00:00 2001 From: Denis Glazachev Date: Sun, 12 Jul 2020 01:40:24 +0400 Subject: [PATCH 062/143] Fix the test: auth_params is a JSON object --- tests/integration/test_grant_and_revoke/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/test_grant_and_revoke/test.py b/tests/integration/test_grant_and_revoke/test.py index cec85a62ef0..9900be4704e 100644 --- a/tests/integration/test_grant_and_revoke/test.py +++ b/tests/integration/test_grant_and_revoke/test.py @@ -200,8 +200,8 @@ def test_introspection(): assert expected_access2 in instance.query("SHOW ACCESS") assert instance.query("SELECT name, storage, auth_type, auth_params, host_ip, host_names, host_names_regexp, host_names_like, default_roles_all, default_roles_list, default_roles_except from system.users WHERE name IN ('A', 'B') ORDER BY name") ==\ - TSV([[ "A", "disk", "no_password", "[]", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ], - [ "B", "disk", "no_password", "[]", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ]]) + TSV([[ "A", "disk", "no_password", "{}", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ], + [ "B", "disk", "no_password", "{}", "['::/0']", "[]", "[]", "[]", 1, "[]", "[]" ]]) assert instance.query("SELECT * from system.grants WHERE user_name IN ('A', 'B') ORDER BY user_name, access_type, grant_option") ==\ TSV([[ "A", "\N", "SELECT", "test", "table", "\N", 0, 0 ], From 8784994d653bb67b72f5bf48dfa1508345a8daf6 Mon Sep 17 00:00:00 2001 From: Ivan Babrou Date: Sat, 11 Jul 2020 18:59:23 -0700 Subject: [PATCH 063/143] Allow conditions outside of PK with exact range Conditions that are outside of PK are marked as `unknown` in `KeyCondition`, so it's safe to allow them, as long as they are always combined by `AND`. --- src/Storages/MergeTree/KeyCondition.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Storages/MergeTree/KeyCondition.cpp b/src/Storages/MergeTree/KeyCondition.cpp index d08ae5dde44..79bbc0e7216 100644 --- a/src/Storages/MergeTree/KeyCondition.cpp +++ b/src/Storages/MergeTree/KeyCondition.cpp @@ -1169,6 +1169,11 @@ bool KeyCondition::matchesExactContinuousRange() const continue; } + if (element.function == RPNElement::Function::FUNCTION_UNKNOWN) + { + continue; + } + return false; } From 204a4af394fc40fc0c450c8d4ec79bda950b7c8b Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sun, 12 Jul 2020 05:31:58 +0300 Subject: [PATCH 064/143] Rollback insertion error in Log engines #12402 --- src/Common/FileChecker.cpp | 45 +++++++++++++------ src/Common/FileChecker.h | 12 +++-- src/Disks/DiskLocal.cpp | 8 ++++ src/Disks/DiskLocal.h | 2 + src/Disks/DiskMemory.cpp | 11 +++++ src/Disks/DiskMemory.h | 2 + src/Disks/IDisk.cpp | 10 +++++ src/Disks/IDisk.h | 3 ++ src/Storages/StorageLog.cpp | 38 +++++++++++++--- src/Storages/StorageLog.h | 1 + src/Storages/StorageStripeLog.cpp | 41 +++++++++++++---- src/Storages/StorageTinyLog.cpp | 36 +++++++++++++-- .../01383_log_broken_table.reference | 3 ++ .../0_stateless/01383_log_broken_table.sh | 40 +++++++++++++++++ 14 files changed, 219 insertions(+), 33 deletions(-) create mode 100644 tests/queries/0_stateless/01383_log_broken_table.reference create mode 100755 tests/queries/0_stateless/01383_log_broken_table.sh diff --git a/src/Common/FileChecker.cpp b/src/Common/FileChecker.cpp index 687b4dccca7..c8e5a039cde 100644 --- a/src/Common/FileChecker.cpp +++ b/src/Common/FileChecker.cpp @@ -12,6 +12,12 @@ namespace DB { +namespace ErrorCodes +{ + extern const int UNEXPECTED_END_OF_FILE; +} + + FileChecker::FileChecker(DiskPtr disk_, const String & file_info_path_) : disk(std::move(disk_)) { setPath(file_info_path_); @@ -24,19 +30,15 @@ void FileChecker::setPath(const String & file_info_path_) tmp_files_info_path = parentPath(files_info_path) + "tmp_" + fileName(files_info_path); } -void FileChecker::update(const String & file_path) +void FileChecker::update(const String & full_file_path) { initialize(); - updateImpl(file_path); - save(); + map[fileName(full_file_path)] = disk->getFileSize(full_file_path); } -void FileChecker::update(const Strings::const_iterator & begin, const Strings::const_iterator & end) +void FileChecker::setEmpty(const String & full_file_path) { - initialize(); - for (auto it = begin; it != end; ++it) - updateImpl(*it); - save(); + map[fileName(full_file_path)] = 0; } CheckResults FileChecker::check() const @@ -73,6 +75,28 @@ CheckResults FileChecker::check() const return results; } +void FileChecker::repair() +{ + for (const auto & name_size : map) + { + const String & name = name_size.first; + size_t expected_size = name_size.second; + String path = parentPath(files_info_path) + name; + + auto real_size = disk->exists(path) ? disk->getFileSize(path) : 0; /// Race condition is Ok. + + if (real_size < expected_size) + throw Exception(ErrorCodes::UNEXPECTED_END_OF_FILE, "Size of {} is less than expected. Size is {} but should be {}.", + path, real_size, expected_size); + + if (real_size > expected_size) + { + LOG_WARNING(&Poco::Logger::get("FileChecker"), "Will truncate file {} that has size {} to size {}", path, real_size, expected_size); + disk->truncateFile(path, expected_size); + } + } +} + void FileChecker::initialize() { if (initialized) @@ -82,11 +106,6 @@ void FileChecker::initialize() initialized = true; } -void FileChecker::updateImpl(const String & file_path) -{ - map[fileName(file_path)] = disk->getFileSize(file_path); -} - void FileChecker::save() const { { diff --git a/src/Common/FileChecker.h b/src/Common/FileChecker.h index 83db397e78c..015d4cadb07 100644 --- a/src/Common/FileChecker.h +++ b/src/Common/FileChecker.h @@ -14,19 +14,25 @@ class FileChecker public: FileChecker(DiskPtr disk_, const String & file_info_path_); void setPath(const String & file_info_path_); - void update(const String & file_path); - void update(const Strings::const_iterator & begin, const Strings::const_iterator & end); + + void update(const String & full_file_path); + void setEmpty(const String & full_file_path); + void save() const; /// Check the files whose parameters are specified in sizes.json CheckResults check() const; + /// Truncate files that have excessive size to the expected size. + /// Throw exception if the file size is less than expected. + /// The purpose of this function is to rollback a group of unfinished writes. + void repair(); + private: /// File name -> size. using Map = std::map; void initialize(); void updateImpl(const String & file_path); - void save() const; void load(Map & local_map, const String & path) const; DiskPtr disk; diff --git a/src/Disks/DiskLocal.cpp b/src/Disks/DiskLocal.cpp index 68f5ee99a7a..f8c1342a2ae 100644 --- a/src/Disks/DiskLocal.cpp +++ b/src/Disks/DiskLocal.cpp @@ -19,6 +19,7 @@ namespace ErrorCodes extern const int EXCESSIVE_ELEMENT_IN_CONFIG; extern const int PATH_ACCESS_DENIED; extern const int INCORRECT_DISK_INDEX; + extern const int CANNOT_TRUNCATE_FILE; } std::mutex DiskLocal::reservation_mutex; @@ -261,6 +262,13 @@ void DiskLocal::createHardLink(const String & src_path, const String & dst_path) DB::createHardLink(disk_path + src_path, disk_path + dst_path); } +void DiskLocal::truncateFile(const String & path, size_t size) +{ + int res = truncate(path.c_str(), size); + if (-1 == res) + throwFromErrnoWithPath("Cannot truncate file " + path, path, ErrorCodes::CANNOT_TRUNCATE_FILE); +} + void DiskLocal::createFile(const String & path) { Poco::File(disk_path + path).createFile(); diff --git a/src/Disks/DiskLocal.h b/src/Disks/DiskLocal.h index 3dab4614d5d..71c4dc0aec9 100644 --- a/src/Disks/DiskLocal.h +++ b/src/Disks/DiskLocal.h @@ -99,6 +99,8 @@ public: void createHardLink(const String & src_path, const String & dst_path) override; + void truncateFile(const String & path, size_t size) override; + const String getType() const override { return "local"; } private: diff --git a/src/Disks/DiskMemory.cpp b/src/Disks/DiskMemory.cpp index 3e43d159ba5..96d9e22c414 100644 --- a/src/Disks/DiskMemory.cpp +++ b/src/Disks/DiskMemory.cpp @@ -408,6 +408,17 @@ void DiskMemory::setReadOnly(const String &) throw Exception("Method setReadOnly is not implemented for memory disks", ErrorCodes::NOT_IMPLEMENTED); } +void DiskMemory::truncateFile(const String & path, size_t size) +{ + std::lock_guard lock(mutex); + + auto file_it = files.find(path); + if (file_it == files.end()) + throw Exception("File '" + path + "' doesn't exist", ErrorCodes::FILE_DOESNT_EXIST); + + file_it->second.data.resize(size); +} + using DiskMemoryPtr = std::shared_ptr; diff --git a/src/Disks/DiskMemory.h b/src/Disks/DiskMemory.h index f7948019fe8..fc265ddef03 100644 --- a/src/Disks/DiskMemory.h +++ b/src/Disks/DiskMemory.h @@ -90,6 +90,8 @@ public: void createHardLink(const String & src_path, const String & dst_path) override; + void truncateFile(const String & path, size_t size) override; + const String getType() const override { return "memory"; } private: diff --git a/src/Disks/IDisk.cpp b/src/Disks/IDisk.cpp index 837ddf1b6b2..8ac3bacd6e3 100644 --- a/src/Disks/IDisk.cpp +++ b/src/Disks/IDisk.cpp @@ -8,6 +8,11 @@ namespace DB { +namespace ErrorCodes +{ + extern const int NOT_IMPLEMENTED; +} + bool IDisk::isDirectoryEmpty(const String & path) { return !iterateDirectory(path)->isValid(); @@ -42,4 +47,9 @@ void IDisk::copy(const String & from_path, const std::shared_ptr & to_dis } } +void IDisk::truncateFile(const String & path, size_t size) +{ + throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Truncate operation is not implemented for disk of type {}", getType()); +} + } diff --git a/src/Disks/IDisk.h b/src/Disks/IDisk.h index 77a52a7a5d6..0a977feb9a1 100644 --- a/src/Disks/IDisk.h +++ b/src/Disks/IDisk.h @@ -172,6 +172,9 @@ public: /// Create hardlink from `src_path` to `dst_path`. virtual void createHardLink(const String & src_path, const String & dst_path) = 0; + /// Truncate file to specified size. + virtual void truncateFile(const String & path, size_t size); + /// Return disk type - "local", "s3", etc. virtual const String getType() const = 0; }; diff --git a/src/Storages/StorageLog.cpp b/src/Storages/StorageLog.cpp index 39fa1d1af70..9cfc906108a 100644 --- a/src/Storages/StorageLog.cpp +++ b/src/Storages/StorageLog.cpp @@ -127,7 +127,12 @@ public: { try { - writeSuffix(); + if (!done) + { + /// Rollback partial writes. + streams.clear(); + storage.file_checker.repair(); + } } catch (...) { @@ -298,7 +303,6 @@ void LogBlockOutputStream::writeSuffix() { if (done) return; - done = true; WrittenStreams written_streams; IDataType::SerializeBinaryBulkSettings settings; @@ -323,9 +327,12 @@ void LogBlockOutputStream::writeSuffix() column_files.push_back(storage.files[name_stream.first].data_file_path); column_files.push_back(storage.marks_file_path); - storage.file_checker.update(column_files.begin(), column_files.end()); + for (const auto & file : column_files) + storage.file_checker.update(file); + storage.file_checker.save(); streams.clear(); + done = true; } @@ -427,6 +434,7 @@ StorageLog::StorageLog( const StorageID & table_id_, const ColumnsDescription & columns_, const ConstraintsDescription & constraints_, + bool attach, size_t max_compress_block_size_) : IStorage(table_id_) , disk(std::move(disk_)) @@ -442,13 +450,31 @@ StorageLog::StorageLog( if (relative_path_.empty()) throw Exception("Storage " + getName() + " requires data path", ErrorCodes::INCORRECT_FILE_NAME); - /// create directories if they do not exist - disk->createDirectories(table_path); + if (!attach) + { + /// create directories if they do not exist + disk->createDirectories(table_path); + } + else + { + try + { + file_checker.repair(); + } + catch (...) + { + tryLogCurrentException(__PRETTY_FUNCTION__); + } + } for (const auto & column : storage_metadata.getColumns().getAllPhysical()) addFiles(column.name, *column.type); marks_file_path = table_path + DBMS_STORAGE_LOG_MARKS_FILE_NAME; + + if (!attach) + for (const auto & file : files) + file_checker.setEmpty(file.second.data_file_path); } @@ -655,7 +681,7 @@ void registerStorageLog(StorageFactory & factory) return StorageLog::create( disk, args.relative_data_path, args.table_id, args.columns, args.constraints, - args.context.getSettings().max_compress_block_size); + args.attach, args.context.getSettings().max_compress_block_size); }, features); } diff --git a/src/Storages/StorageLog.h b/src/Storages/StorageLog.h index d020f906609..96acb1668e2 100644 --- a/src/Storages/StorageLog.h +++ b/src/Storages/StorageLog.h @@ -54,6 +54,7 @@ protected: const StorageID & table_id_, const ColumnsDescription & columns_, const ConstraintsDescription & constraints_, + bool attach, size_t max_compress_block_size_); private: diff --git a/src/Storages/StorageStripeLog.cpp b/src/Storages/StorageStripeLog.cpp index e55cc190f80..ae8162d5f1b 100644 --- a/src/Storages/StorageStripeLog.cpp +++ b/src/Storages/StorageStripeLog.cpp @@ -161,11 +161,12 @@ public: , lock(storage.rwlock) , data_out_file(storage.table_path + "data.bin") , data_out_compressed(storage.disk->writeFile(data_out_file, DBMS_DEFAULT_BUFFER_SIZE, WriteMode::Append)) - , data_out(*data_out_compressed, CompressionCodecFactory::instance().getDefaultCodec(), storage.max_compress_block_size) + , data_out(std::make_unique( + *data_out_compressed, CompressionCodecFactory::instance().getDefaultCodec(), storage.max_compress_block_size)) , index_out_file(storage.table_path + "index.mrk") , index_out_compressed(storage.disk->writeFile(index_out_file, DBMS_DEFAULT_BUFFER_SIZE, WriteMode::Append)) - , index_out(*index_out_compressed) - , block_out(data_out, 0, metadata_snapshot->getSampleBlock(), false, &index_out, storage.disk->getFileSize(data_out_file)) + , index_out(std::make_unique(*index_out_compressed)) + , block_out(*data_out, 0, metadata_snapshot->getSampleBlock(), false, index_out.get(), storage.disk->getFileSize(data_out_file)) { } @@ -173,7 +174,16 @@ public: { try { - writeSuffix(); + if (!done) + { + /// Rollback partial writes. + data_out.reset(); + data_out_compressed.reset(); + index_out.reset(); + index_out_compressed.reset(); + + storage.file_checker.repair(); + } } catch (...) { @@ -194,13 +204,14 @@ public: return; block_out.writeSuffix(); - data_out.next(); + data_out->next(); data_out_compressed->next(); - index_out.next(); + index_out->next(); index_out_compressed->next(); storage.file_checker.update(data_out_file); storage.file_checker.update(index_out_file); + storage.file_checker.save(); done = true; } @@ -212,10 +223,10 @@ private: String data_out_file; std::unique_ptr data_out_compressed; - CompressedWriteBuffer data_out; + std::unique_ptr data_out; String index_out_file; std::unique_ptr index_out_compressed; - CompressedWriteBuffer index_out; + std::unique_ptr index_out; NativeBlockOutputStream block_out; bool done = false; @@ -249,6 +260,20 @@ StorageStripeLog::StorageStripeLog( { /// create directories if they do not exist disk->createDirectories(table_path); + + file_checker.setEmpty(table_path + "data.bin"); + file_checker.setEmpty(table_path + "index.mrk"); + } + else + { + try + { + file_checker.repair(); + } + catch (...) + { + tryLogCurrentException(__PRETTY_FUNCTION__); + } } } diff --git a/src/Storages/StorageTinyLog.cpp b/src/Storages/StorageTinyLog.cpp index ef8c30cacbe..3d2c20e6b50 100644 --- a/src/Storages/StorageTinyLog.cpp +++ b/src/Storages/StorageTinyLog.cpp @@ -118,7 +118,17 @@ public: { try { - writeSuffix(); + std::cerr << "Done: " << done << "\n"; + + if (!done) + { + /// Rollback partial writes. + streams.clear(); + + std::cerr << "Repairing\n"; + + storage.file_checker.repair(); + } } catch (...) { @@ -277,11 +287,13 @@ void TinyLogBlockOutputStream::writeSuffix() { if (done) return; - done = true; /// If nothing was written - leave the table in initial state. if (streams.empty()) + { + done = true; return; + } WrittenStreams written_streams; IDataType::SerializeBinaryBulkSettings settings; @@ -303,9 +315,12 @@ void TinyLogBlockOutputStream::writeSuffix() for (auto & pair : streams) column_files.push_back(storage.files[pair.first].data_file_path); - storage.file_checker.update(column_files.begin(), column_files.end()); + for (const auto & file : column_files) + storage.file_checker.update(file); + storage.file_checker.save(); streams.clear(); + done = true; } @@ -352,9 +367,24 @@ StorageTinyLog::StorageTinyLog( /// create directories if they do not exist disk->createDirectories(table_path); } + else + { + try + { + file_checker.repair(); + } + catch (...) + { + tryLogCurrentException(__PRETTY_FUNCTION__); + } + } for (const auto & col : storage_metadata.getColumns().getAllPhysical()) addFiles(col.name, *col.type); + + if (!attach) + for (const auto & file : files) + file_checker.setEmpty(file.second.data_file_path); } diff --git a/tests/queries/0_stateless/01383_log_broken_table.reference b/tests/queries/0_stateless/01383_log_broken_table.reference new file mode 100644 index 00000000000..1bc7c914e46 --- /dev/null +++ b/tests/queries/0_stateless/01383_log_broken_table.reference @@ -0,0 +1,3 @@ +Testing TinyLog +Testing StripeLog +Testing Log diff --git a/tests/queries/0_stateless/01383_log_broken_table.sh b/tests/queries/0_stateless/01383_log_broken_table.sh new file mode 100755 index 00000000000..2afac11e7c2 --- /dev/null +++ b/tests/queries/0_stateless/01383_log_broken_table.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd) +CLICKHOUSE_CLIENT_SERVER_LOGS_LEVEL=none +. $CURDIR/../shell_config.sh + + +function test() +{ + ENGINE=$1 + MAX_MEM=4096 + + echo "Testing $ENGINE" + + $CLICKHOUSE_CLIENT --query "DROP TABLE IF EXISTS log"; + $CLICKHOUSE_CLIENT --query "CREATE TABLE log (x UInt64, y UInt64, z UInt64) ENGINE = $ENGINE"; + + while true; do + MAX_MEM=$((2 * $MAX_MEM)) + + $CLICKHOUSE_CLIENT --query "INSERT INTO log SELECT number, number, number FROM numbers(1000000)" --max_memory_usage $MAX_MEM > ${CLICKHOUSE_TMP}/insert_result 2>&1 + + grep -o -F 'Memory limit' ${CLICKHOUSE_TMP}/insert_result || cat ${CLICKHOUSE_TMP}/insert_result + + $CLICKHOUSE_CLIENT --query "SELECT count(), sum(x + y + z) FROM log" > ${CLICKHOUSE_TMP}/select_result 2>&1; + + grep -o -F 'File not found' ${CLICKHOUSE_TMP}/select_result || cat ${CLICKHOUSE_TMP}/select_result + + [[ $MAX_MEM -gt 200000000 ]] && break; + done + + $CLICKHOUSE_CLIENT --query "DROP TABLE log"; +} + +test TinyLog | grep -v -P '^(Memory limit|0\t0|File not found|[1-9]000000\t)' +test StripeLog | grep -v -P '^(Memory limit|0\t0|File not found|[1-9]000000\t)' +test Log | grep -v -P '^(Memory limit|0\t0|File not found|[1-9]000000\t)' + +rm "${CLICKHOUSE_TMP}/insert_result" +rm "${CLICKHOUSE_TMP}/select_result" From 49f60ef3a43223dffe593ca071256c553819daf5 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sun, 12 Jul 2020 08:26:33 +0300 Subject: [PATCH 065/143] Fix build --- src/Storages/tests/gtest_storage_log.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Storages/tests/gtest_storage_log.cpp b/src/Storages/tests/gtest_storage_log.cpp index c97adaf118d..a9a4ea4ad0e 100644 --- a/src/Storages/tests/gtest_storage_log.cpp +++ b/src/Storages/tests/gtest_storage_log.cpp @@ -31,7 +31,7 @@ DB::StoragePtr createStorage(DB::DiskPtr & disk) names_and_types.emplace_back("a", std::make_shared()); StoragePtr table = StorageLog::create( - disk, "table/", StorageID("test", "test"), ColumnsDescription{names_and_types}, ConstraintsDescription{}, 1048576); + disk, "table/", StorageID("test", "test"), ColumnsDescription{names_and_types}, ConstraintsDescription{}, false, 1048576); table->startup(); From dac5e1ce4d4905f74d7cc3264bf59098ea3829b8 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Mon, 13 Jul 2020 08:24:55 +0300 Subject: [PATCH 066/143] SystemLog: do not log under mutex --- src/Interpreters/SystemLog.h | 70 ++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/Interpreters/SystemLog.h b/src/Interpreters/SystemLog.h index 7d533a3bab7..5d88e200f6c 100644 --- a/src/Interpreters/SystemLog.h +++ b/src/Interpreters/SystemLog.h @@ -233,46 +233,56 @@ void SystemLog::add(const LogElement & element) /// Otherwise the tests like 01017_uniqCombined_memory_usage.sql will be flacky. auto temporarily_disable_memory_tracker = getCurrentMemoryTrackerActionLock(); - std::lock_guard lock(mutex); + /// Should not log messages under mutex. + bool queue_is_half_full = false; - if (is_shutdown) - return; - - if (queue.size() == DBMS_SYSTEM_LOG_QUEUE_SIZE / 2) { - // The queue more than half full, time to flush. - // We only check for strict equality, because messages are added one - // by one, under exclusive lock, so we will see each message count. - // It is enough to only wake the flushing thread once, after the message - // count increases past half available size. - const uint64_t queue_end = queue_front_index + queue.size(); - if (requested_flush_before < queue_end) - requested_flush_before = queue_end; + std::unique_lock lock(mutex); - flush_event.notify_all(); - LOG_INFO(log, "Queue is half full for system log '{}'.", demangle(typeid(*this).name())); - } + if (is_shutdown) + return; - if (queue.size() >= DBMS_SYSTEM_LOG_QUEUE_SIZE) - { - // Ignore all further entries until the queue is flushed. - // Log a message about that. Don't spam it -- this might be especially - // problematic in case of trace log. Remember what the front index of the - // queue was when we last logged the message. If it changed, it means the - // queue was flushed, and we can log again. - if (queue_front_index != logged_queue_full_at_index) + if (queue.size() == DBMS_SYSTEM_LOG_QUEUE_SIZE / 2) { - logged_queue_full_at_index = queue_front_index; + queue_is_half_full = true; - // TextLog sets its logger level to 0, so this log is a noop and - // there is no recursive logging. - LOG_ERROR(log, "Queue is full for system log '{}' at {}", demangle(typeid(*this).name()), queue_front_index); + // The queue more than half full, time to flush. + // We only check for strict equality, because messages are added one + // by one, under exclusive lock, so we will see each message count. + // It is enough to only wake the flushing thread once, after the message + // count increases past half available size. + const uint64_t queue_end = queue_front_index + queue.size(); + if (requested_flush_before < queue_end) + requested_flush_before = queue_end; + + flush_event.notify_all(); } - return; + if (queue.size() >= DBMS_SYSTEM_LOG_QUEUE_SIZE) + { + // Ignore all further entries until the queue is flushed. + // Log a message about that. Don't spam it -- this might be especially + // problematic in case of trace log. Remember what the front index of the + // queue was when we last logged the message. If it changed, it means the + // queue was flushed, and we can log again. + if (queue_front_index != logged_queue_full_at_index) + { + logged_queue_full_at_index = queue_front_index; + + // TextLog sets its logger level to 0, so this log is a noop and + // there is no recursive logging. + lock.unlock(); + LOG_ERROR(log, "Queue is full for system log '{}' at {}", demangle(typeid(*this).name()), queue_front_index); + } + + return; + } + + queue.push_back(element); } - queue.push_back(element); + if (queue_is_half_full) + LOG_INFO(log, "Queue is half full for system log '{}'.", demangle(typeid(*this).name())); } From 26fca949bda003c8b2d3d66b6b54cb7a29d448d0 Mon Sep 17 00:00:00 2001 From: Anton Ivashkin Date: Fri, 10 Jul 2020 12:32:34 +0300 Subject: [PATCH 067/143] add profiling events from S3 request to system.events and system.query_log --- .../runner/compose/docker_compose_minio.yml | 1 + src/Common/ProfileEvents.cpp | 15 ++ src/IO/ReadBufferFromS3.cpp | 18 +- src/IO/S3/PocoHTTPClient.cpp | 70 ++++++++ src/IO/WriteBufferFromS3.cpp | 7 + .../test_profile_events_s3/__init__.py | 0 .../configs/config.d/storage_conf.xml | 21 +++ .../test_profile_events_s3/configs/config.xml | 35 ++++ .../test_profile_events_s3/configs/users.xml | 24 +++ .../test_profile_events_s3/test.py | 160 ++++++++++++++++++ 10 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 tests/integration/test_profile_events_s3/__init__.py create mode 100644 tests/integration/test_profile_events_s3/configs/config.d/storage_conf.xml create mode 100644 tests/integration/test_profile_events_s3/configs/config.xml create mode 100644 tests/integration/test_profile_events_s3/configs/users.xml create mode 100644 tests/integration/test_profile_events_s3/test.py diff --git a/docker/test/integration/runner/compose/docker_compose_minio.yml b/docker/test/integration/runner/compose/docker_compose_minio.yml index eefbe4abff5..defa4b604c4 100644 --- a/docker/test/integration/runner/compose/docker_compose_minio.yml +++ b/docker/test/integration/runner/compose/docker_compose_minio.yml @@ -10,6 +10,7 @@ services: environment: MINIO_ACCESS_KEY: minio MINIO_SECRET_KEY: minio123 + MINIO_PROMETHEUS_AUTH_TYPE: public command: server --address :9001 /data1-1 healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9001/minio/health/live"] diff --git a/src/Common/ProfileEvents.cpp b/src/Common/ProfileEvents.cpp index 5c88b2ee849..7adf82570ba 100644 --- a/src/Common/ProfileEvents.cpp +++ b/src/Common/ProfileEvents.cpp @@ -212,6 +212,21 @@ M(NotCreatedLogEntryForMerge, "Log entry to merge parts in ReplicatedMergeTree is not created due to concurrent log update by another replica.") \ M(CreatedLogEntryForMutation, "Successfully created log entry to mutate parts in ReplicatedMergeTree.") \ M(NotCreatedLogEntryForMutation, "Log entry to mutate parts in ReplicatedMergeTree is not created due to concurrent log update by another replica.") \ + \ + M(S3ReadMicroseconds, "Time of GET and HEAD requests to S3 storage.") \ + M(S3ReadBytes, "Read bytes (incoming) in GET and HEAD requests to S3 storage.") \ + M(S3ReadRequestsCount, "Number of GET and HEAD requests to S3 storage.") \ + M(S3ReadRequestsErrors, "Number of non-throttling errors in GET and HEAD requests to S3 storage.") \ + M(S3ReadRequestsThrottling, "Number of 429 and 503 errors in GET and HEAD requests to S3 storage.") \ + M(S3ReadRequestsRedirects, "Number of redirects in GET and HEAD requests to S3 storage.") \ + \ + M(S3WriteMicroseconds, "Time of POST, DELETE, PUT and PATCH requests to S3 storage.") \ + M(S3WriteBytes, "Write bytes (outgoing) in POST, DELETE, PUT and PATCH requests to S3 storage.") \ + M(S3WriteRequestsCount, "Number of POST, DELETE, PUT and PATCH requests to S3 storage.") \ + M(S3WriteRequestsErrors, "Number of non-throttling errors in POST, DELETE, PUT and PATCH requests to S3 storage.") \ + M(S3WriteRequestsThrottling, "Number of 429 and 503 errors in POST, DELETE, PUT and PATCH requests to S3 storage.") \ + M(S3WriteRequestsRedirects, "Number of redirects in POST, DELETE, PUT and PATCH requests to S3 storage.") \ + namespace ProfileEvents { diff --git a/src/IO/ReadBufferFromS3.cpp b/src/IO/ReadBufferFromS3.cpp index 472607d0e21..3287609d3d4 100644 --- a/src/IO/ReadBufferFromS3.cpp +++ b/src/IO/ReadBufferFromS3.cpp @@ -4,6 +4,7 @@ # include # include +# include # include # include @@ -11,6 +12,12 @@ # include +namespace ProfileEvents +{ + extern const Event S3ReadMicroseconds; + extern const Event S3ReadBytes; +} + namespace DB { namespace ErrorCodes @@ -27,6 +34,7 @@ ReadBufferFromS3::ReadBufferFromS3( { } + bool ReadBufferFromS3::nextImpl() { if (!initialized) @@ -35,9 +43,17 @@ bool ReadBufferFromS3::nextImpl() initialized = true; } - if (!impl->next()) + Stopwatch watch(CLOCK_MONOTONIC); + auto res = impl->next(); + watch.stop(); + ProfileEvents::increment(ProfileEvents::S3ReadMicroseconds, watch.elapsedMicroseconds()); + + if (!res) return false; internal_buffer = impl->buffer(); + + ProfileEvents::increment(ProfileEvents::S3ReadBytes, internal_buffer.size()); + working_buffer = internal_buffer; return true; } diff --git a/src/IO/S3/PocoHTTPClient.cpp b/src/IO/S3/PocoHTTPClient.cpp index f2315861bf5..0954fa98655 100644 --- a/src/IO/S3/PocoHTTPClient.cpp +++ b/src/IO/S3/PocoHTTPClient.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,21 @@ #include #include +namespace ProfileEvents +{ + extern const Event S3ReadMicroseconds; + extern const Event S3ReadRequestsCount; + extern const Event S3ReadRequestsErrors; + extern const Event S3ReadRequestsThrottling; + extern const Event S3ReadRequestsRedirects; + + extern const Event S3WriteMicroseconds; + extern const Event S3WriteRequestsCount; + extern const Event S3WriteRequestsErrors; + extern const Event S3WriteRequestsThrottling; + extern const Event S3WriteRequestsRedirects; +} + namespace DB::ErrorCodes { extern const int TOO_MANY_REDIRECTS; @@ -62,6 +78,40 @@ void PocoHTTPClient::MakeRequestInternal( auto uri = request.GetUri().GetURIString(); LOG_DEBUG(log, "Make request to: {}", uri); + enum ES3MetricType + { + Microseconds = 0, + Count, + Errors, + Throttling, + Redirects, + }; + + auto SelectMetric = [&request](int type) + { + const ProfileEvents::Event events_map[][2] = { + {ProfileEvents::S3ReadMicroseconds, ProfileEvents::S3WriteMicroseconds}, + {ProfileEvents::S3ReadRequestsCount, ProfileEvents::S3WriteRequestsCount}, + {ProfileEvents::S3ReadRequestsErrors, ProfileEvents::S3WriteRequestsErrors}, + {ProfileEvents::S3ReadRequestsThrottling, ProfileEvents::S3WriteRequestsThrottling}, + {ProfileEvents::S3ReadRequestsRedirects, ProfileEvents::S3WriteRequestsRedirects}, + }; + + switch (request.GetMethod()) + { + case Aws::Http::HttpMethod::HTTP_GET: + case Aws::Http::HttpMethod::HTTP_HEAD: + return events_map[type][0]; // Read + case Aws::Http::HttpMethod::HTTP_POST: + case Aws::Http::HttpMethod::HTTP_DELETE: + case Aws::Http::HttpMethod::HTTP_PUT: + case Aws::Http::HttpMethod::HTTP_PATCH: + return events_map[type][1]; // Write + } + }; + + ProfileEvents::increment(SelectMetric(Count)); + const int MAX_REDIRECT_ATTEMPTS = 10; try { @@ -107,11 +157,15 @@ void PocoHTTPClient::MakeRequestInternal( poco_request.set(header_name, header_value); Poco::Net::HTTPResponse poco_response; + + Stopwatch watch(CLOCK_MONOTONIC); + auto & request_body_stream = session->sendRequest(poco_request); if (request.GetContentBody()) { LOG_TRACE(log, "Writing request body."); + if (attempt > 0) /// rewind content body buffer. { request.GetContentBody()->clear(); @@ -124,6 +178,9 @@ void PocoHTTPClient::MakeRequestInternal( LOG_TRACE(log, "Receiving response..."); auto & response_body_stream = session->receiveResponse(poco_response); + watch.stop(); + ProfileEvents::increment(SelectMetric(Microseconds), watch.elapsedMicroseconds()); + int status_code = static_cast(poco_response.getStatus()); LOG_DEBUG(log, "Response status: {}, {}", status_code, poco_response.getReason()); @@ -133,6 +190,8 @@ void PocoHTTPClient::MakeRequestInternal( uri = location; LOG_DEBUG(log, "Redirecting request to new location: {}", location); + ProfileEvents::increment(SelectMetric(Redirects)); + continue; } @@ -154,6 +213,15 @@ void PocoHTTPClient::MakeRequestInternal( response->SetClientErrorType(Aws::Client::CoreErrors::NETWORK_CONNECTION); response->SetClientErrorMessage(error_message); + + if (status_code == 429 || status_code == 503) + { // API throttling + ProfileEvents::increment(SelectMetric(Throttling)); + } + else + { + ProfileEvents::increment(SelectMetric(Errors)); + } } else response->GetResponseStream().SetUnderlyingStream(std::make_shared(session, response_body_stream)); @@ -168,6 +236,8 @@ void PocoHTTPClient::MakeRequestInternal( tryLogCurrentException(log, fmt::format("Failed to make request to: {}", uri)); response->SetClientErrorType(Aws::Client::CoreErrors::NETWORK_CONNECTION); response->SetClientErrorMessage(getCurrentExceptionMessage(false)); + + ProfileEvents::increment(SelectMetric(Errors)); } } } diff --git a/src/IO/WriteBufferFromS3.cpp b/src/IO/WriteBufferFromS3.cpp index 946871d9c63..27da2c3c879 100644 --- a/src/IO/WriteBufferFromS3.cpp +++ b/src/IO/WriteBufferFromS3.cpp @@ -14,6 +14,11 @@ # include +namespace ProfileEvents +{ + extern const Event S3WriteBytes; +} + namespace DB { // S3 protocol does not allow to have multipart upload with more than 10000 parts. @@ -53,6 +58,8 @@ void WriteBufferFromS3::nextImpl() temporary_buffer->write(working_buffer.begin(), offset()); + ProfileEvents::increment(ProfileEvents::S3WriteBytes, offset()); + last_part_size += offset(); if (last_part_size > minimum_upload_part_size) diff --git a/tests/integration/test_profile_events_s3/__init__.py b/tests/integration/test_profile_events_s3/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/integration/test_profile_events_s3/configs/config.d/storage_conf.xml b/tests/integration/test_profile_events_s3/configs/config.d/storage_conf.xml new file mode 100644 index 00000000000..b32770095fc --- /dev/null +++ b/tests/integration/test_profile_events_s3/configs/config.d/storage_conf.xml @@ -0,0 +1,21 @@ + + + + + s3 + http://minio1:9001/root/data/ + minio + minio123 + + + + + +
+ s3 +
+
+
+
+
+
diff --git a/tests/integration/test_profile_events_s3/configs/config.xml b/tests/integration/test_profile_events_s3/configs/config.xml new file mode 100644 index 00000000000..b83cbbac0a7 --- /dev/null +++ b/tests/integration/test_profile_events_s3/configs/config.xml @@ -0,0 +1,35 @@ + + + + trace + /var/log/clickhouse-server/clickhouse-server.log + /var/log/clickhouse-server/clickhouse-server.err.log + 1000M + 10 + + + + system + query_log
+ toYYYYMM(event_date) + 1000 +
+ + 9000 + 127.0.0.1 + + + + true + none + + AcceptCertificateHandler + + + + + 500 + 5368709120 + ./clickhouse/ + users.xml +
diff --git a/tests/integration/test_profile_events_s3/configs/users.xml b/tests/integration/test_profile_events_s3/configs/users.xml new file mode 100644 index 00000000000..95c83bf3dfe --- /dev/null +++ b/tests/integration/test_profile_events_s3/configs/users.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + ::/0 + + default + default + 1 + + + + + + + + diff --git a/tests/integration/test_profile_events_s3/test.py b/tests/integration/test_profile_events_s3/test.py new file mode 100644 index 00000000000..f98505757bf --- /dev/null +++ b/tests/integration/test_profile_events_s3/test.py @@ -0,0 +1,160 @@ +import logging +import random +import string +import time +import re +import requests + +import pytest +from helpers.cluster import ClickHouseCluster + +logging.getLogger().setLevel(logging.INFO) +logging.getLogger().addHandler(logging.StreamHandler()) + + +@pytest.fixture(scope="module") +def cluster(): + try: + cluster = ClickHouseCluster(__file__) + + cluster.add_instance("node", config_dir="configs", with_minio=True) + + logging.info("Starting cluster...") + cluster.start() + logging.info("Cluster started") + + yield cluster + finally: + cluster.shutdown() + + +init_list = { + "S3ReadMicroseconds" : 0, + "S3ReadBytes" : 0, + "S3ReadRequestsCount" : 0, + "S3ReadRequestsErrorsTotal" : 0, + "S3ReadRequestsErrors503" : 0, + "S3ReadRequestsRedirects" : 0, + "S3WriteMicroseconds" : 0, + "S3WriteBytes" : 0, + "S3WriteRequestsCount" : 0, + "S3WriteRequestsErrorsTotal" : 0, + "S3WriteRequestsErrors503" : 0, + "S3WriteRequestsRedirects" : 0, +} + +def get_s3_events(instance): + result = init_list.copy() + events = instance.query("SELECT event,value FROM system.events WHERE event LIKE 'S3%'").split("\n") + for event in events: + ev = event.split("\t") + if len(ev) == 2: + result[ev[0]] = int(ev[1]) + return result + + +def get_minio_stat(cluster): + result = { + "get_requests" : 0, + "set_requests" : 0, + "errors" : 0, + "rx_bytes" : 0, + "tx_bytes" : 0, + } + stat = requests.get(url="http://{}:{}/minio/prometheus/metrics".format("localhost", cluster.minio_port)).text.split("\n") + for line in stat: + x = re.search("s3_requests_total(\{.*\})?\s(\d+)(\s.*)?", line) + if x != None: + y = re.search(".*api=\"(get|list|head|select).*", x.group(1)) + if y != None: + result["get_requests"] += int(x.group(2)) + else: + result["set_requests"] += int(x.group(2)) + x = re.search("s3_errors_total(\{.*\})?\s(\d+)(\s.*)?", line) + if x != None: + result["errors"] += int(x.group(2)) + x = re.search("s3_rx_bytes_total(\{.*\})?\s([\d\.e\+\-]+)(\s.*)?", line) + if x != None: + result["tx_bytes"] += float(x.group(2)) + x = re.search("s3_tx_bytes_total(\{.*\})?\s([\d\.e\+\-]+)(\s.*)?", line) + if x != None: + result["rx_bytes"] += float(x.group(2)) + return result + + +def get_query_stat(instance, hint): + result = init_list.copy() + instance.query("SYSTEM FLUSH LOGS") + events = instance.query(''' + SELECT ProfileEvents.Names, ProfileEvents.Values + FROM system.query_log + ARRAY JOIN ProfileEvents + WHERE type != 1 AND query LIKE '%{}%' + '''.format(hint.replace("'", "\\'"))).split("\n") + for event in events: + ev = event.split("\t") + if len(ev) == 2: + if ev[0].startswith("S3"): + result[ev[0]] += int(ev[1]) + return result + + +def get_minio_size(cluster): + minio = cluster.minio_client + size = 0 + for obj in minio.list_objects(cluster.minio_bucket, 'data/'): + size += obj.size + return size + + +def test_profile_events(cluster): + instance = cluster.instances["node"] + + instance.query("SYSTEM FLUSH LOGS") + + instance.query("DROP TABLE IF EXISTS test_s3.test_s3") + instance.query("DROP DATABASE IF EXISTS test_s3") + instance.query("CREATE DATABASE IF NOT EXISTS test_s3") + + metrics0 = get_s3_events(instance) + minio0 = get_minio_stat(cluster) + + query1 = "CREATE TABLE test_s3.test_s3 (key UInt32, value UInt32) ENGINE=MergeTree PRIMARY KEY key ORDER BY key SETTINGS storage_policy='s3'" + instance.query(query1) + + size1 = get_minio_size(cluster) + metrics1 = get_s3_events(instance) + minio1 = get_minio_stat(cluster) + + assert metrics1["S3ReadRequestsCount"] - metrics0["S3ReadRequestsCount"] == minio1["get_requests"] - minio0["get_requests"] - 1 # 1 from get_minio_size + assert metrics1["S3WriteRequestsCount"] - metrics0["S3WriteRequestsCount"] == minio1["set_requests"] - minio0["set_requests"] + stat1 = get_query_stat(instance, query1) + for metric in stat1: + assert stat1[metric] == metrics1[metric] - metrics0[metric] + assert metrics1["S3WriteBytes"] - metrics0["S3WriteBytes"] == size1 + + query2 = "INSERT INTO test_s3.test_s3 FORMAT Values" + instance.query(query2 + " (1,1)") + + size2 = get_minio_size(cluster) + metrics2 = get_s3_events(instance) + minio2 = get_minio_stat(cluster) + + assert metrics2["S3ReadRequestsCount"] - metrics1["S3ReadRequestsCount"] == minio2["get_requests"] - minio1["get_requests"] - 1 # 1 from get_minio_size + assert metrics2["S3WriteRequestsCount"] - metrics1["S3WriteRequestsCount"] == minio2["set_requests"] - minio1["set_requests"] + stat2 = get_query_stat(instance, query2) + for metric in stat2: + assert stat2[metric] == metrics2[metric] - metrics1[metric] + assert metrics2["S3WriteBytes"] - metrics1["S3WriteBytes"] == size2 - size1 + + query3 = "SELECT * from test_s3.test_s3" + assert instance.query(query3) == "1\t1\n" + + metrics3 = get_s3_events(instance) + minio3 = get_minio_stat(cluster) + + assert metrics3["S3ReadRequestsCount"] - metrics2["S3ReadRequestsCount"] == minio3["get_requests"] - minio2["get_requests"] + assert metrics3["S3WriteRequestsCount"] - metrics2["S3WriteRequestsCount"] == minio3["set_requests"] - minio2["set_requests"] + stat3 = get_query_stat(instance, query3) + for metric in stat3: + assert stat3[metric] == metrics3[metric] - metrics2[metric] From 4da37fb3a0d633326cb112952b7c172795e09296 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Mon, 13 Jul 2020 14:40:46 +0300 Subject: [PATCH 068/143] Fix decimal aggregate perf test --- tests/performance/decimal_aggregates.xml | 33 ++++++++++-------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/tests/performance/decimal_aggregates.xml b/tests/performance/decimal_aggregates.xml index fa9f947abc9..5911fd61161 100644 --- a/tests/performance/decimal_aggregates.xml +++ b/tests/performance/decimal_aggregates.xml @@ -1,16 +1,11 @@ - - - definitely_no_such_table - - - 20G + 30G CREATE TABLE t (x UInt64, d32 Decimal32(3), d64 Decimal64(4), d128 Decimal128(5)) ENGINE = Memory - INSERT INTO t SELECT number AS x, x % 1000000 AS d32, x AS d64, x d128 FROM numbers_mt(200000000) SETTINGS max_threads = 8 + INSERT INTO t SELECT number AS x, x % 1000000 AS d32, x AS d64, x d128 FROM numbers_mt(500000000) SETTINGS max_threads = 8 DROP TABLE IF EXISTS t SELECT min(d32), max(d32), argMin(x, d32), argMax(x, d32) FROM t @@ -21,21 +16,21 @@ SELECT avg(d64), sum(d64), sumWithOverflow(d64) FROM t SELECT avg(d128), sum(d128), sumWithOverflow(d128) FROM t - SELECT uniq(d32), uniqCombined(d32), uniqExact(d32), uniqHLL12(d32) FROM t LIMIT 100000 - SELECT uniq(d64), uniqCombined(d64), uniqExact(d64), uniqHLL12(d64) FROM t LIMIT 100000 - SELECT uniq(d128), uniqCombined(d128), uniqExact(d128), uniqHLL12(d128) FROM t LIMIT 100000 + SELECT uniq(d32), uniqCombined(d32), uniqExact(d32), uniqHLL12(d32) FROM (SELECT * FROM t LIMIT 10000000) + SELECT uniq(d64), uniqCombined(d64), uniqExact(d64), uniqHLL12(d64) FROM (SELECT * FROM t LIMIT 10000000 + SELECT uniq(d128), uniqCombined(d128), uniqExact(d128), uniqHLL12(d128) FROM (SELECT * FROM t LIMIT 10000000) - SELECT median(d32), medianExact(d32), medianExactWeighted(d32, 2) FROM t LIMIT 100000 - SELECT median(d64), medianExact(d64), medianExactWeighted(d64, 2) FROM t LIMIT 100000 - SELECT median(d128), medianExact(d128), medianExactWeighted(d128, 2) FROM t LIMIT 100000 + SELECT median(d32), medianExact(d32), medianExactWeighted(d32, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT median(d64), medianExact(d64), medianExactWeighted(d64, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT median(d128), medianExact(d128), medianExactWeighted(d128, 2) FROM (SELECT * FROM t LIMIT 10000000) - SELECT quantile(d32), quantileExact(d32), quantileExactWeighted(d32, 2) FROM t LIMIT 100000 - SELECT quantile(d64), quantileExact(d64), quantileExactWeighted(d64, 2) FROM t LIMIT 100000 - SELECT quantile(d128), quantileExact(d128), quantileExactWeighted(d128, 2) FROM t LIMIT 100000 + SELECT quantile(d32), quantileExact(d32), quantileExactWeighted(d32, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT quantile(d64), quantileExact(d64), quantileExactWeighted(d64, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT quantile(d128), quantileExact(d128), quantileExactWeighted(d128, 2) FROM (SELECT * FROM t LIMIT 10000000) - SELECT quantilesExact(0.1, 0.9)(d32), quantilesExactWeighted(0.1, 0.9)(d32, 2) FROM t LIMIT 100000 - SELECT quantilesExact(0.1, 0.9)(d64), quantilesExactWeighted(0.1, 0.9)(d64, 2) FROM t LIMIT 100000 - SELECT quantilesExact(0.1, 0.9)(d128), quantilesExactWeighted(0.1, 0.9)(d128, 2) FROM t LIMIT 100000 + SELECT quantilesExact(0.1, 0.9)(d32), quantilesExactWeighted(0.1, 0.9)(d32, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT quantilesExact(0.1, 0.9)(d64), quantilesExactWeighted(0.1, 0.9)(d64, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT quantilesExact(0.1, 0.9)(d128), quantilesExactWeighted(0.1, 0.9)(d128, 2) FROM (SELECT * FROM t LIMIT 10000000) SELECT varPop(d32), varSamp(d32), stddevPop(d32) FROM t SELECT varPop(d64), varSamp(d64), stddevPop(d64) FROM t From 7d1b0a06f26c96af23935ada420d36740f81a735 Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Mon, 13 Jul 2020 22:36:56 +0200 Subject: [PATCH 069/143] * Moving to updating configs without restart. --- tests/testflows/helpers/cluster.py | 10 +++++++ tests/testflows/ldap/tests/common.py | 39 +++++++++++++++++----------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/tests/testflows/helpers/cluster.py b/tests/testflows/helpers/cluster.py index e087b3b5b9d..9f86d44124c 100644 --- a/tests/testflows/helpers/cluster.py +++ b/tests/testflows/helpers/cluster.py @@ -167,6 +167,16 @@ class Cluster(object): self.docker_compose += f" --project-directory \"{docker_compose_project_dir}\" --file \"{docker_compose_file_path}\"" self.lock = threading.Lock() + def shell(self, node): + """Returns unique shell terminal to be used. + """ + if node is None: + return Shell() + + return Shell(command=[ + "/bin/bash", "--noediting", "-c", f"{self.docker_compose} exec {node} bash --noediting" + ], name=node) + def bash(self, node, timeout=60): """Returns thread-local bash terminal to a specific node. diff --git a/tests/testflows/ldap/tests/common.py b/tests/testflows/ldap/tests/common.py index e0897cb6e9f..d0783dd2686 100644 --- a/tests/testflows/ldap/tests/common.py +++ b/tests/testflows/ldap/tests/common.py @@ -61,23 +61,32 @@ def add_config(config, timeout=20, restart=False): with When("I output the content of the config"): debug(config.content) - with When("I add the config", description=config.path): - command = f"cat < {config.path}\n{config.content}\nHEREDOC" - node.command(command, steps=False, exitcode=0) + with node.cluster.shell(node.name) as bash: + bash.expect(bash.prompt) + bash.send("tail -f /var/log/clickhouse-server/clickhouse-server.log") - with Then(f"{config.preprocessed_name} should be updated", description=f"timeout {timeout}"): - started = time.time() - command = f"cat /var/lib/clickhouse/preprocessed_configs/{config.preprocessed_name} | grep {config.uid}{' > /dev/null' if not settings.debug else ''}" - while time.time() - started < timeout: - exitcode = node.command(command, steps=False).exitcode - if exitcode == 0: - break - time.sleep(1) - assert exitcode == 0, error() + with When("I add the config", description=config.path): + command = f"cat < {config.path}\n{config.content}\nHEREDOC" + node.command(command, steps=False, exitcode=0) - if restart: - with When("I restart ClickHouse to apply the config changes"): - node.restart(safe=False) + with Then(f"{config.preprocessed_name} should be updated", description=f"timeout {timeout}"): + started = time.time() + command = f"cat /var/lib/clickhouse/preprocessed_configs/{config.preprocessed_name} | grep {config.uid}{' > /dev/null' if not settings.debug else ''}" + while time.time() - started < timeout: + exitcode = node.command(command, steps=False).exitcode + if exitcode == 0: + break + time.sleep(1) + assert exitcode == 0, error() + +# if restart: +# with When("I restart ClickHouse to apply the config changes"): +# node.restart(safe=False) + + with When("I wait for config to be loaded"): + started = time.time() + bash.expect(f"ConfigReloader: Loaded config '/etc/clickhouse-server/{config.preprocessed_name}', performed update on configuration", timeout=timeout) + time.sleep(10) yield finally: with Finally(f"I remove {config.name}"): From e57e51e812bd24c0b700355e9c3d0b46c3e69f31 Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Mon, 13 Jul 2020 22:38:06 +0200 Subject: [PATCH 070/143] * Removing hard coded sleep. --- tests/testflows/ldap/tests/common.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/testflows/ldap/tests/common.py b/tests/testflows/ldap/tests/common.py index d0783dd2686..45489eec243 100644 --- a/tests/testflows/ldap/tests/common.py +++ b/tests/testflows/ldap/tests/common.py @@ -86,7 +86,6 @@ def add_config(config, timeout=20, restart=False): with When("I wait for config to be loaded"): started = time.time() bash.expect(f"ConfigReloader: Loaded config '/etc/clickhouse-server/{config.preprocessed_name}', performed update on configuration", timeout=timeout) - time.sleep(10) yield finally: with Finally(f"I remove {config.name}"): From cb0b74af863cd35e69bcdcf0ac2aaea0ec430452 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Tue, 14 Jul 2020 11:56:01 +0300 Subject: [PATCH 071/143] Fix AggregateFunctionAvg serialization backwards compatibility --- src/AggregateFunctions/AggregateFunctionAvg.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/AggregateFunctions/AggregateFunctionAvg.h b/src/AggregateFunctions/AggregateFunctionAvg.h index 95b4836c336..73b250547ea 100644 --- a/src/AggregateFunctions/AggregateFunctionAvg.h +++ b/src/AggregateFunctions/AggregateFunctionAvg.h @@ -20,6 +20,7 @@ template struct AggregateFunctionAvgData { using NumeratorType = T; + using DenominatorType = Denominator; T numerator = 0; Denominator denominator = 0; @@ -73,13 +74,21 @@ public: void serialize(ConstAggregateDataPtr place, WriteBuffer & buf) const override { writeBinary(this->data(place).numerator, buf); - writeBinary(this->data(place).denominator, buf); + + if constexpr (std::is_integral_v) + writeVarUInt(this->data(place).denominator, buf); + else /// Floating point denominator type can be used + writeBinary(this->data(place).denominator, buf); } void deserialize(AggregateDataPtr place, ReadBuffer & buf, Arena *) const override { readBinary(this->data(place).numerator, buf); - readBinary(this->data(place).denominator, buf); + + if constexpr (std::is_integral_v) + readVarUInt(this->data(place).denominator, buf); + else /// Floating point denominator type can be used + readBinary(this->data(place).denominator, buf); } void insertResultInto(AggregateDataPtr place, IColumn & to, Arena *) const override From 2c3ae1600f6df56fb21ccbb99efbb65104bbccf6 Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Tue, 14 Jul 2020 13:44:40 +0200 Subject: [PATCH 072/143] Adding `-n 0` to the tail command. --- tests/testflows/ldap/tests/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testflows/ldap/tests/common.py b/tests/testflows/ldap/tests/common.py index 45489eec243..070feae3c02 100644 --- a/tests/testflows/ldap/tests/common.py +++ b/tests/testflows/ldap/tests/common.py @@ -63,7 +63,7 @@ def add_config(config, timeout=20, restart=False): with node.cluster.shell(node.name) as bash: bash.expect(bash.prompt) - bash.send("tail -f /var/log/clickhouse-server/clickhouse-server.log") + bash.send("tail -n 0 -f /var/log/clickhouse-server/clickhouse-server.log") with When("I add the config", description=config.path): command = f"cat < {config.path}\n{config.content}\nHEREDOC" From 86a6a5e2c6b607d3273415855fd05e2107fef6f6 Mon Sep 17 00:00:00 2001 From: alesapin Date: Tue, 14 Jul 2020 15:17:35 +0300 Subject: [PATCH 073/143] Less tests to run --- docker/test/fasttest/run.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index fe44234fe64..cc6034d182e 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -89,6 +89,8 @@ do sleep 0.1 done -clickhouse-test --no-long --testname --shard --zookeeper --skip parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt +TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close" + +clickhouse-test --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt mv /var/log/clickhouse-server/* /test_output From 527d33aa2bc198c8ace7ae7c42b7521e703d1279 Mon Sep 17 00:00:00 2001 From: Anton Ivashkin Date: Tue, 14 Jul 2020 15:26:22 +0300 Subject: [PATCH 074/143] Fix gcc build, fix codestyle --- src/IO/S3/PocoHTTPClient.cpp | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/IO/S3/PocoHTTPClient.cpp b/src/IO/S3/PocoHTTPClient.cpp index 0954fa98655..b9c100cf40b 100644 --- a/src/IO/S3/PocoHTTPClient.cpp +++ b/src/IO/S3/PocoHTTPClient.cpp @@ -32,6 +32,7 @@ namespace ProfileEvents namespace DB::ErrorCodes { + extern const int NOT_IMPLEMENTED; extern const int TOO_MANY_REDIRECTS; } @@ -78,16 +79,18 @@ void PocoHTTPClient::MakeRequestInternal( auto uri = request.GetUri().GetURIString(); LOG_DEBUG(log, "Make request to: {}", uri); - enum ES3MetricType + enum class ES3MetricType { - Microseconds = 0, + Microseconds, Count, Errors, Throttling, Redirects, + + EnumSize, }; - - auto SelectMetric = [&request](int type) + + auto SelectMetric = [&request](ES3MetricType type) { const ProfileEvents::Event events_map[][2] = { {ProfileEvents::S3ReadMicroseconds, ProfileEvents::S3WriteMicroseconds}, @@ -97,20 +100,24 @@ void PocoHTTPClient::MakeRequestInternal( {ProfileEvents::S3ReadRequestsRedirects, ProfileEvents::S3WriteRequestsRedirects}, }; + static_assert((sizeof(events_map) / sizeof(events_map[0])) == static_cast(ES3MetricType::EnumSize)); + switch (request.GetMethod()) { case Aws::Http::HttpMethod::HTTP_GET: case Aws::Http::HttpMethod::HTTP_HEAD: - return events_map[type][0]; // Read + return events_map[static_cast(type)][0]; // Read case Aws::Http::HttpMethod::HTTP_POST: case Aws::Http::HttpMethod::HTTP_DELETE: case Aws::Http::HttpMethod::HTTP_PUT: case Aws::Http::HttpMethod::HTTP_PATCH: - return events_map[type][1]; // Write + return events_map[static_cast(type)][1]; // Write } + + throw Exception(String("Unsupported request method"), ErrorCodes::NOT_IMPLEMENTED); }; - - ProfileEvents::increment(SelectMetric(Count)); + + ProfileEvents::increment(SelectMetric(ES3MetricType::Count)); const int MAX_REDIRECT_ATTEMPTS = 10; try @@ -179,7 +186,7 @@ void PocoHTTPClient::MakeRequestInternal( auto & response_body_stream = session->receiveResponse(poco_response); watch.stop(); - ProfileEvents::increment(SelectMetric(Microseconds), watch.elapsedMicroseconds()); + ProfileEvents::increment(SelectMetric(ES3MetricType::Microseconds), watch.elapsedMicroseconds()); int status_code = static_cast(poco_response.getStatus()); LOG_DEBUG(log, "Response status: {}, {}", status_code, poco_response.getReason()); @@ -190,7 +197,7 @@ void PocoHTTPClient::MakeRequestInternal( uri = location; LOG_DEBUG(log, "Redirecting request to new location: {}", location); - ProfileEvents::increment(SelectMetric(Redirects)); + ProfileEvents::increment(SelectMetric(ES3MetricType::Redirects)); continue; } @@ -216,11 +223,11 @@ void PocoHTTPClient::MakeRequestInternal( if (status_code == 429 || status_code == 503) { // API throttling - ProfileEvents::increment(SelectMetric(Throttling)); + ProfileEvents::increment(SelectMetric(ES3MetricType::Throttling)); } else { - ProfileEvents::increment(SelectMetric(Errors)); + ProfileEvents::increment(SelectMetric(ES3MetricType::Errors)); } } else @@ -237,7 +244,7 @@ void PocoHTTPClient::MakeRequestInternal( response->SetClientErrorType(Aws::Client::CoreErrors::NETWORK_CONNECTION); response->SetClientErrorMessage(getCurrentExceptionMessage(false)); - ProfileEvents::increment(SelectMetric(Errors)); + ProfileEvents::increment(SelectMetric(ES3MetricType::Errors)); } } } From fa6fc719ab9f32e7a4501f7411327024a6433b78 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Tue, 14 Jul 2020 15:55:25 +0300 Subject: [PATCH 075/143] fixup --- tests/performance/decimal_aggregates.xml | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/performance/decimal_aggregates.xml b/tests/performance/decimal_aggregates.xml index 5911fd61161..3c210240ab3 100644 --- a/tests/performance/decimal_aggregates.xml +++ b/tests/performance/decimal_aggregates.xml @@ -16,23 +16,23 @@ SELECT avg(d64), sum(d64), sumWithOverflow(d64) FROM t SELECT avg(d128), sum(d128), sumWithOverflow(d128) FROM t - SELECT uniq(d32), uniqCombined(d32), uniqExact(d32), uniqHLL12(d32) FROM (SELECT * FROM t LIMIT 10000000) - SELECT uniq(d64), uniqCombined(d64), uniqExact(d64), uniqHLL12(d64) FROM (SELECT * FROM t LIMIT 10000000 - SELECT uniq(d128), uniqCombined(d128), uniqExact(d128), uniqHLL12(d128) FROM (SELECT * FROM t LIMIT 10000000) + SELECT uniq(d32), uniqCombined(d32), uniqExact(d32), uniqHLL12(d32) FROM (SELECT * FROM t LIMIT 10000000) + SELECT uniq(d64), uniqCombined(d64), uniqExact(d64), uniqHLL12(d64) FROM (SELECT * FROM t LIMIT 10000000) + SELECT uniq(d128), uniqCombined(d128), uniqExact(d128), uniqHLL12(d128) FROM (SELECT * FROM t LIMIT 1000000) - SELECT median(d32), medianExact(d32), medianExactWeighted(d32, 2) FROM (SELECT * FROM t LIMIT 10000000) - SELECT median(d64), medianExact(d64), medianExactWeighted(d64, 2) FROM (SELECT * FROM t LIMIT 10000000) - SELECT median(d128), medianExact(d128), medianExactWeighted(d128, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT median(d32), medianExact(d32), medianExactWeighted(d32, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT median(d64), medianExact(d64), medianExactWeighted(d64, 2) FROM (SELECT * FROM t LIMIT 1000000) + SELECT median(d128), medianExact(d128), medianExactWeighted(d128, 2) FROM (SELECT * FROM t LIMIT 1000000) - SELECT quantile(d32), quantileExact(d32), quantileExactWeighted(d32, 2) FROM (SELECT * FROM t LIMIT 10000000) - SELECT quantile(d64), quantileExact(d64), quantileExactWeighted(d64, 2) FROM (SELECT * FROM t LIMIT 10000000) - SELECT quantile(d128), quantileExact(d128), quantileExactWeighted(d128, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT quantile(d32), quantileExact(d32), quantileExactWeighted(d32, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT quantile(d64), quantileExact(d64), quantileExactWeighted(d64, 2) FROM (SELECT * FROM t LIMIT 1000000) + SELECT quantile(d128), quantileExact(d128), quantileExactWeighted(d128, 2) FROM (SELECT * FROM t LIMIT 1000000) - SELECT quantilesExact(0.1, 0.9)(d32), quantilesExactWeighted(0.1, 0.9)(d32, 2) FROM (SELECT * FROM t LIMIT 10000000) - SELECT quantilesExact(0.1, 0.9)(d64), quantilesExactWeighted(0.1, 0.9)(d64, 2) FROM (SELECT * FROM t LIMIT 10000000) - SELECT quantilesExact(0.1, 0.9)(d128), quantilesExactWeighted(0.1, 0.9)(d128, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT quantilesExact(0.1, 0.9)(d32), quantilesExactWeighted(0.1, 0.9)(d32, 2) FROM (SELECT * FROM t LIMIT 10000000) + SELECT quantilesExact(0.1, 0.9)(d64), quantilesExactWeighted(0.1, 0.9)(d64, 2) FROM (SELECT * FROM t LIMIT 1000000) + SELECT quantilesExact(0.1, 0.9)(d128), quantilesExactWeighted(0.1, 0.9)(d128, 2) FROM (SELECT * FROM t LIMIT 1000000) SELECT varPop(d32), varSamp(d32), stddevPop(d32) FROM t - SELECT varPop(d64), varSamp(d64), stddevPop(d64) FROM t - SELECT varPop(d128), varSamp(d128), stddevPop(d128) FROM t + SELECT varPop(d64), varSamp(d64), stddevPop(d64) FROM (SELECT * FROM t LIMIT 1000000) + SELECT varPop(d128), varSamp(d128), stddevPop(d128) FROM (SELECT * FROM t LIMIT 1000000) From c400048a48da52dbb7bbbedf334e49f004797f53 Mon Sep 17 00:00:00 2001 From: alesapin Date: Tue, 14 Jul 2020 17:47:23 +0300 Subject: [PATCH 076/143] Check server able to restart in stateless tests --- docker/test/stress/Dockerfile | 25 ++-------------- docker/test/stress/run.sh | 56 +++++++++++++++++++++++++++++++++++ docker/test/stress/stress | 46 ++++++++-------------------- 3 files changed, 71 insertions(+), 56 deletions(-) create mode 100755 docker/test/stress/run.sh diff --git a/docker/test/stress/Dockerfile b/docker/test/stress/Dockerfile index 12e2d5579b4..6855a632df4 100644 --- a/docker/test/stress/Dockerfile +++ b/docker/test/stress/Dockerfile @@ -23,28 +23,7 @@ RUN apt-get update -y \ brotli COPY ./stress /stress +COPY run.sh / ENV DATASETS="hits visits" - -CMD dpkg -i package_folder/clickhouse-common-static_*.deb; \ - dpkg -i package_folder/clickhouse-common-static-dbg_*.deb; \ - dpkg -i package_folder/clickhouse-server_*.deb; \ - dpkg -i package_folder/clickhouse-client_*.deb; \ - dpkg -i package_folder/clickhouse-test_*.deb; \ - ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/; \ - ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/; \ - echo "TSAN_OPTIONS='halt_on_error=1 history_size=7 ignore_noninstrumented_modules=1 verbosity=1'" >> /etc/environment; \ - echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment; \ - echo "ASAN_OPTIONS='malloc_context_size=10 verbosity=1 allocator_release_to_os_interval_ms=10000'" >> /etc/environment; \ - service clickhouse-server start && sleep 5 \ - && /s3downloader --dataset-names $DATASETS \ - && chmod 777 -R /var/lib/clickhouse \ - && clickhouse-client --query "ATTACH DATABASE IF NOT EXISTS datasets ENGINE = Ordinary" \ - && clickhouse-client --query "CREATE DATABASE IF NOT EXISTS test" \ - && service clickhouse-server restart && sleep 5 \ - && clickhouse-client --query "SHOW TABLES FROM datasets" \ - && clickhouse-client --query "SHOW TABLES FROM test" \ - && clickhouse-client --query "RENAME TABLE datasets.hits_v1 TO test.hits" \ - && clickhouse-client --query "RENAME TABLE datasets.visits_v1 TO test.visits" \ - && clickhouse-client --query "SHOW TABLES FROM test" \ - && ./stress --output-folder test_output --skip-func-tests "$SKIP_TESTS_OPTION" +CMD ["/bin/bash", "/run.sh"] diff --git a/docker/test/stress/run.sh b/docker/test/stress/run.sh new file mode 100755 index 00000000000..eeedcaec1f8 --- /dev/null +++ b/docker/test/stress/run.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +dpkg -i package_folder/clickhouse-common-static_*.deb +dpkg -i package_folder/clickhouse-common-static-dbg_*.deb +dpkg -i package_folder/clickhouse-server_*.deb +dpkg -i package_folder/clickhouse-client_*.deb +dpkg -i package_folder/clickhouse-test_*.deb + +function wait_server() +{ + counter=0 + until clickhouse-client --query "SELECT 1" + do + if [ "$counter" -gt 120 ] + then + break + fi + sleep 0.5 + counter=$(($counter + 1)) + done +} + +ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/ +ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/ + +echo "TSAN_OPTIONS='halt_on_error=1 history_size=7 ignore_noninstrumented_modules=1 verbosity=1'" >> /etc/environment +echo "UBSAN_OPTIONS='print_stacktrace=1'" >> /etc/environment +echo "ASAN_OPTIONS='malloc_context_size=10 verbosity=1 allocator_release_to_os_interval_ms=10000'" >> /etc/environment + +service clickhouse-server start + +wait_server + +/s3downloader --dataset-names $DATASETS +chmod 777 -R /var/lib/clickhouse +clickhouse-client --query "ATTACH DATABASE IF NOT EXISTS datasets ENGINE = Ordinary" +clickhouse-client --query "CREATE DATABASE IF NOT EXISTS test" +service clickhouse-server restart + +wait_server + +clickhouse-client --query "SHOW TABLES FROM datasets" +clickhouse-client --query "SHOW TABLES FROM test" +clickhouse-client --query "RENAME TABLE datasets.hits_v1 TO test.hits" +clickhouse-client --query "RENAME TABLE datasets.visits_v1 TO test.visits" +clickhouse-client --query "SHOW TABLES FROM test" + +./stress --output-folder test_output --skip-func-tests "$SKIP_TESTS_OPTION" + +service clickhouse-server restart + +wait_server + +clickhouse-client --query "SELECT 'Server successfuly started'" || echo 'Server failed to start' + +mv /var/log/clickhouse-server/* /test_output diff --git a/docker/test/stress/stress b/docker/test/stress/stress index b5ed4dbd85d..b107dc59829 100755 --- a/docker/test/stress/stress +++ b/docker/test/stress/stress @@ -41,15 +41,6 @@ def run_func_test(cmd, output_prefix, num_processes, skip_tests_option): return pipes -def check_clickhouse_alive(cmd): - try: - logging.info("Checking ClickHouse still alive") - check_call("{} --query \"select 'Still alive'\"".format(cmd), shell=True) - return True - except: - return False - - if __name__ == "__main__": logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s') parser = argparse.ArgumentParser(description="ClickHouse script for running stresstest") @@ -65,29 +56,18 @@ if __name__ == "__main__": args = parser.parse_args() func_pipes = [] perf_process = None - try: - perf_process = run_perf_test(args.perf_test_cmd, args.perf_test_xml_path, args.output_folder) - func_pipes = run_func_test(args.test_cmd, args.output_folder, args.num_parallel, args.skip_func_tests) + perf_process = run_perf_test(args.perf_test_cmd, args.perf_test_xml_path, args.output_folder) + func_pipes = run_func_test(args.test_cmd, args.output_folder, args.num_parallel, args.skip_func_tests) - logging.info("Will wait functests to finish") - while True: - retcodes = [] - for p in func_pipes: - if p.poll() is not None: - retcodes.append(p.returncode) - if len(retcodes) == len(func_pipes): - break - logging.info("Finished %s from %s processes", len(retcodes), len(func_pipes)) - time.sleep(5) + logging.info("Will wait functests to finish") + while True: + retcodes = [] + for p in func_pipes: + if p.poll() is not None: + retcodes.append(p.returncode) + if len(retcodes) == len(func_pipes): + break + logging.info("Finished %s from %s processes", len(retcodes), len(func_pipes)) + time.sleep(5) - if not check_clickhouse_alive(args.client_cmd): - raise Exception("Stress failed, results in logs") - else: - logging.info("Stress is ok") - except Exception as ex: - raise ex - finally: - if os.path.exists(args.server_log_folder): - logging.info("Copying server log files") - for log_file in os.listdir(args.server_log_folder): - shutil.copy(os.path.join(args.server_log_folder, log_file), os.path.join(args.output_folder, log_file)) + logging.info("Stress test finished") From 749deaf12268440c554d58469d2d37926ffaca99 Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Tue, 14 Jul 2020 17:00:19 +0200 Subject: [PATCH 077/143] Adding wait for config reload message when deleting old configuration file. --- tests/testflows/ldap/tests/common.py | 31 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/tests/testflows/ldap/tests/common.py b/tests/testflows/ldap/tests/common.py index 070feae3c02..a27013b1797 100644 --- a/tests/testflows/ldap/tests/common.py +++ b/tests/testflows/ldap/tests/common.py @@ -89,18 +89,27 @@ def add_config(config, timeout=20, restart=False): yield finally: with Finally(f"I remove {config.name}"): - with By("removing the config file", description=config.path): - node.command(f"rm -rf {config.path}", exitcode=0) + with node.cluster.shell(node.name) as bash: + bash.expect(bash.prompt) + bash.send("tail -n 0 -f /var/log/clickhouse-server/clickhouse-server.log") + + with By("removing the config file", description=config.path): + node.command(f"rm -rf {config.path}", exitcode=0) + + with Then(f"{config.preprocessed_name} should be updated"): + started = time.time() + command = f"cat /var/lib/clickhouse/preprocessed_configs/{config.preprocessed_name} | grep '{config.uid}'{' > /dev/null' if not settings.debug else ''}" + while time.time() - started < timeout: + exitcode = node.command(command, steps=False).exitcode + if exitcode == 1: + break + time.sleep(1) + assert exitcode == 1, error() + + with When("I wait for config to be loaded"): + started = time.time() + bash.expect(f"ConfigReloader: Loaded config '/etc/clickhouse-server/{config.preprocessed_name}', performed update on configuration", timeout=timeout) - with Then(f"{config.preprocessed_name} should be updated"): - started = time.time() - command = f"cat /var/lib/clickhouse/preprocessed_configs/{config.preprocessed_name} | grep '{config.uid}'{' > /dev/null' if not settings.debug else ''}" - while time.time() - started < timeout: - exitcode = node.command(command, steps=False).exitcode - if exitcode == 1: - break - time.sleep(1) - assert exitcode == 1, error() def create_ldap_servers_config_content(servers, config_d_dir="/etc/clickhouse-server/config.d", config_file="ldap_servers.xml"): """Create LDAP servers configuration content. From c483de8a3511bd155adf697d05b641ba91f51240 Mon Sep 17 00:00:00 2001 From: alesapin Date: Tue, 14 Jul 2020 18:00:24 +0300 Subject: [PATCH 078/143] Check result in separate file --- docker/test/stress/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/stress/run.sh b/docker/test/stress/run.sh index eeedcaec1f8..ae7bbee7939 100755 --- a/docker/test/stress/run.sh +++ b/docker/test/stress/run.sh @@ -51,6 +51,6 @@ service clickhouse-server restart wait_server -clickhouse-client --query "SELECT 'Server successfuly started'" || echo 'Server failed to start' +clickhouse-client --query "SELECT 'Server successfuly started'" > /test_output/alive_check.txt || echo 'Server failed to start' > /test_output/alive_check.txt mv /var/log/clickhouse-server/* /test_output From 6498fe81232ce107ff68560c3e05632468eb8c02 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Tue, 14 Jul 2020 18:11:49 +0300 Subject: [PATCH 079/143] Publish repo snapshot in perf test package --- docker/packager/binary/build.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docker/packager/binary/build.sh b/docker/packager/binary/build.sh index 791fd18d80c..e34c3c01c7b 100755 --- a/docker/packager/binary/build.sh +++ b/docker/packager/binary/build.sh @@ -33,6 +33,24 @@ then rm /output/clickhouse-odbc-bridge ||: cp -r ../docker/test/performance-comparison /output/scripts ||: + + # We have to know the revision that corresponds to this binary build. + # It is not the nominal SHA from pull/*/head, but the pull/*/merge, which is + # head merged to master by github, at some point after the PR is updated. + # There are some quirks to consider: + # - apparently the real SHA is not recorded in system.build_options; + # - it can change at any time as github pleases, so we can't just record + # the SHA and use it later, it might become inaccessible; + # - CI has an immutable snapshot of repository that it uses for all checks + # for a given nominal SHA, but it is not accessible outside Yandex. + # This is why we add this repository snapshot from CI to the performance test + # package. + mkdir /output/ch + git -C /output/ch init --bare + git -C /output/ch remote add origin .. + git -C /output/ch fetch --no-tags --depth 50 origin HEAD + git -C /output/ch reset --soft FETCH_HEAD + git -C /output/ch log -5 fi # May be set for split build or for performance test. From a31109f0237cc88bf77f03f961e944f092eb9319 Mon Sep 17 00:00:00 2001 From: alesapin Date: Tue, 14 Jul 2020 21:44:57 +0300 Subject: [PATCH 080/143] Better submdoules --- cmake/find/msgpack.cmake | 2 +- docker/test/fasttest/run.sh | 39 ++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/cmake/find/msgpack.cmake b/cmake/find/msgpack.cmake index db7dbea42db..102ea619f6a 100644 --- a/cmake/find/msgpack.cmake +++ b/cmake/find/msgpack.cmake @@ -18,7 +18,7 @@ else() find_path(MSGPACK_INCLUDE_DIR NAMES msgpack.hpp PATHS ${MSGPACK_INCLUDE_PATHS}) endif() -if (MSG_PACK_INCLUDE_DIR) +if (MSGPACK_INCLUDE_DIR) set(USE_MSGPACK 1) endif() diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index cc6034d182e..4fa13ed3730 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -24,8 +24,45 @@ else fi fi +git submodule update --init --recursive contrib/boost | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -git submodule update --init --recursive | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt +git submodule update --init --recursive contrib/zlib-ng | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/libxml2 | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/poco | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/libunwind | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/ryu | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/fmtlib | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/cctz | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/libcpuid | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/replxx | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/double-conversion | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/libcxx | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/libcxxabi | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/libc-headers | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/lz4 | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/zstd | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/fastops | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/rapidjson | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/re2 | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt + +git submodule update --init --recursive contrib/sparsehash-c11 | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -DENABLE_CAPNP=0 -DENABLE_RDKAFKA=0 -DENABLE_ICU=0 -DENABLE_POCO_NETSSL=0 -DENABLE_ODBC=0 -DENABLE_MYSQL=0 -DENABLE_SSL=0 -DENABLE_POCO_NETSSL=0 -DENABLE_CASSANDRA=0 -DENABLE_PARQUET=0 -DENABLE_AVRO=0 -DENABLE_EMBEDDED_COMPILER=0 -DENABLE_PROTOBUF=0 -DENABLE_H3=0 -DENABLE_TESTS=0 -DENABLE_UTILS=0 -DENABLE_ODBC=0 -DENABLE_GSASL_LIBRARY=0 -DENABLE_THINLTO=0 -DENABLE_MSGPACK=0 -DENABLE_LDAP=0 -DUSE_SNAPPY=0 -DENABLE_HYPERSCAN=0" From cdca798d2a2cd8b8e8db84ff8a18aa86365729f2 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Wed, 15 Jul 2020 00:56:35 +0300 Subject: [PATCH 081/143] Update build.sh --- docker/packager/binary/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/packager/binary/build.sh b/docker/packager/binary/build.sh index e34c3c01c7b..6b6a02bb55b 100755 --- a/docker/packager/binary/build.sh +++ b/docker/packager/binary/build.sh @@ -47,7 +47,7 @@ then # package. mkdir /output/ch git -C /output/ch init --bare - git -C /output/ch remote add origin .. + git -C /output/ch remote add origin /build git -C /output/ch fetch --no-tags --depth 50 origin HEAD git -C /output/ch reset --soft FETCH_HEAD git -C /output/ch log -5 From b6654138693e1bcc0e61afb801ac0f05298f9bfc Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Wed, 15 Jul 2020 01:53:34 +0300 Subject: [PATCH 082/143] Improve performance of TestKeeper --- src/Common/ZooKeeper/TestKeeper.cpp | 114 +++++++++++++++++++--------- 1 file changed, 79 insertions(+), 35 deletions(-) diff --git a/src/Common/ZooKeeper/TestKeeper.cpp b/src/Common/ZooKeeper/TestKeeper.cpp index a734d218ff6..6e408750099 100644 --- a/src/Common/ZooKeeper/TestKeeper.cpp +++ b/src/Common/ZooKeeper/TestKeeper.cpp @@ -5,6 +5,7 @@ #include #include +#include namespace Coordination @@ -25,11 +26,14 @@ static String baseName(const String & path) } +using Undo = std::function; + + struct TestKeeperRequest : virtual Request { virtual bool isMutable() const { return false; } virtual ResponsePtr createResponse() const = 0; - virtual ResponsePtr process(TestKeeper::Container & container, int64_t zxid) const = 0; + virtual std::pair process(TestKeeper::Container & container, int64_t zxid) const = 0; virtual void processWatches(TestKeeper::Watches & /*watches*/, TestKeeper::Watches & /*list_watches*/) const {} }; @@ -69,7 +73,7 @@ struct TestKeeperCreateRequest final : CreateRequest, TestKeeperRequest TestKeeperCreateRequest() = default; explicit TestKeeperCreateRequest(const CreateRequest & base) : CreateRequest(base) {} ResponsePtr createResponse() const override; - ResponsePtr process(TestKeeper::Container & container, int64_t zxid) const override; + std::pair process(TestKeeper::Container & container, int64_t zxid) const override; void processWatches(TestKeeper::Watches & node_watches, TestKeeper::Watches & list_watches) const override { @@ -83,7 +87,7 @@ struct TestKeeperRemoveRequest final : RemoveRequest, TestKeeperRequest explicit TestKeeperRemoveRequest(const RemoveRequest & base) : RemoveRequest(base) {} bool isMutable() const override { return true; } ResponsePtr createResponse() const override; - ResponsePtr process(TestKeeper::Container & container, int64_t zxid) const override; + std::pair process(TestKeeper::Container & container, int64_t zxid) const override; void processWatches(TestKeeper::Watches & node_watches, TestKeeper::Watches & list_watches) const override { @@ -94,14 +98,14 @@ struct TestKeeperRemoveRequest final : RemoveRequest, TestKeeperRequest struct TestKeeperExistsRequest final : ExistsRequest, TestKeeperRequest { ResponsePtr createResponse() const override; - ResponsePtr process(TestKeeper::Container & container, int64_t zxid) const override; + std::pair process(TestKeeper::Container & container, int64_t zxid) const override; }; struct TestKeeperGetRequest final : GetRequest, TestKeeperRequest { TestKeeperGetRequest() = default; ResponsePtr createResponse() const override; - ResponsePtr process(TestKeeper::Container & container, int64_t zxid) const override; + std::pair process(TestKeeper::Container & container, int64_t zxid) const override; }; struct TestKeeperSetRequest final : SetRequest, TestKeeperRequest @@ -110,7 +114,7 @@ struct TestKeeperSetRequest final : SetRequest, TestKeeperRequest explicit TestKeeperSetRequest(const SetRequest & base) : SetRequest(base) {} bool isMutable() const override { return true; } ResponsePtr createResponse() const override; - ResponsePtr process(TestKeeper::Container & container, int64_t zxid) const override; + std::pair process(TestKeeper::Container & container, int64_t zxid) const override; void processWatches(TestKeeper::Watches & node_watches, TestKeeper::Watches & list_watches) const override { @@ -121,7 +125,7 @@ struct TestKeeperSetRequest final : SetRequest, TestKeeperRequest struct TestKeeperListRequest final : ListRequest, TestKeeperRequest { ResponsePtr createResponse() const override; - ResponsePtr process(TestKeeper::Container & container, int64_t zxid) const override; + std::pair process(TestKeeper::Container & container, int64_t zxid) const override; }; struct TestKeeperCheckRequest final : CheckRequest, TestKeeperRequest @@ -129,7 +133,7 @@ struct TestKeeperCheckRequest final : CheckRequest, TestKeeperRequest TestKeeperCheckRequest() = default; explicit TestKeeperCheckRequest(const CheckRequest & base) : CheckRequest(base) {} ResponsePtr createResponse() const override; - ResponsePtr process(TestKeeper::Container & container, int64_t zxid) const override; + std::pair process(TestKeeper::Container & container, int64_t zxid) const override; }; struct TestKeeperMultiRequest final : MultiRequest, TestKeeperRequest @@ -169,13 +173,15 @@ struct TestKeeperMultiRequest final : MultiRequest, TestKeeperRequest } ResponsePtr createResponse() const override; - ResponsePtr process(TestKeeper::Container & container, int64_t zxid) const override; + std::pair process(TestKeeper::Container & container, int64_t zxid) const override; }; -ResponsePtr TestKeeperCreateRequest::process(TestKeeper::Container & container, int64_t zxid) const +std::pair TestKeeperCreateRequest::process(TestKeeper::Container & container, int64_t zxid) const { CreateResponse response; + Undo undo; + if (container.count(path)) { response.error = Error::ZNODEEXISTS; @@ -219,7 +225,18 @@ ResponsePtr TestKeeperCreateRequest::process(TestKeeper::Container & container, } response.path_created = path_created; - container.emplace(std::move(path_created), std::move(created_node)); + container.emplace(path_created, std::move(created_node)); + + undo = [&container, path_created, is_sequential = is_sequential, parent_path = it->first] + { + container.erase(path_created); + auto & undo_parent = container.at(parent_path); + --undo_parent.stat.cversion; + --undo_parent.stat.numChildren; + + if (is_sequential) + --undo_parent.seq_num; + }; ++it->second.stat.cversion; ++it->second.stat.numChildren; @@ -228,12 +245,13 @@ ResponsePtr TestKeeperCreateRequest::process(TestKeeper::Container & container, } } - return std::make_shared(response); + return { std::make_shared(response), undo }; } -ResponsePtr TestKeeperRemoveRequest::process(TestKeeper::Container & container, int64_t) const +std::pair TestKeeperRemoveRequest::process(TestKeeper::Container & container, int64_t) const { RemoveResponse response; + Undo undo; auto it = container.find(path); if (it == container.end()) @@ -250,17 +268,26 @@ ResponsePtr TestKeeperRemoveRequest::process(TestKeeper::Container & container, } else { + auto prev_node = it->second; container.erase(it); auto & parent = container.at(parentPath(path)); --parent.stat.numChildren; ++parent.stat.cversion; response.error = Error::ZOK; + + undo = [prev_node, &container, path = path] + { + container.emplace(path, prev_node); + auto & undo_parent = container.at(parentPath(path)); + ++undo_parent.stat.numChildren; + --undo_parent.stat.cversion; + }; } - return std::make_shared(response); + return { std::make_shared(response), undo }; } -ResponsePtr TestKeeperExistsRequest::process(TestKeeper::Container & container, int64_t) const +std::pair TestKeeperExistsRequest::process(TestKeeper::Container & container, int64_t) const { ExistsResponse response; @@ -275,10 +302,10 @@ ResponsePtr TestKeeperExistsRequest::process(TestKeeper::Container & container, response.error = Error::ZNONODE; } - return std::make_shared(response); + return { std::make_shared(response), {} }; } -ResponsePtr TestKeeperGetRequest::process(TestKeeper::Container & container, int64_t) const +std::pair TestKeeperGetRequest::process(TestKeeper::Container & container, int64_t) const { GetResponse response; @@ -294,12 +321,13 @@ ResponsePtr TestKeeperGetRequest::process(TestKeeper::Container & container, int response.error = Error::ZOK; } - return std::make_shared(response); + return { std::make_shared(response), {} }; } -ResponsePtr TestKeeperSetRequest::process(TestKeeper::Container & container, int64_t zxid) const +std::pair TestKeeperSetRequest::process(TestKeeper::Container & container, int64_t zxid) const { SetResponse response; + Undo undo; auto it = container.find(path); if (it == container.end()) @@ -308,6 +336,8 @@ ResponsePtr TestKeeperSetRequest::process(TestKeeper::Container & container, int } else if (version == -1 || version == it->second.stat.version) { + auto prev_node = it->second; + it->second.data = data; ++it->second.stat.version; it->second.stat.mzxid = zxid; @@ -316,16 +346,22 @@ ResponsePtr TestKeeperSetRequest::process(TestKeeper::Container & container, int ++container.at(parentPath(path)).stat.cversion; response.stat = it->second.stat; response.error = Error::ZOK; + + undo = [prev_node, &container, path = path] + { + container.at(path) = prev_node; + --container.at(parentPath(path)).stat.cversion; + }; } else { response.error = Error::ZBADVERSION; } - return std::make_shared(response); + return { std::make_shared(response), undo }; } -ResponsePtr TestKeeperListRequest::process(TestKeeper::Container & container, int64_t) const +std::pair TestKeeperListRequest::process(TestKeeper::Container & container, int64_t) const { ListResponse response; @@ -344,18 +380,22 @@ ResponsePtr TestKeeperListRequest::process(TestKeeper::Container & container, in path_prefix += '/'; /// Fairly inefficient. - for (auto child_it = container.upper_bound(path_prefix); child_it != container.end() && startsWith(child_it->first, path_prefix); ++child_it) + for (auto child_it = container.upper_bound(path_prefix); + child_it != container.end() && startsWith(child_it->first, path_prefix); + ++child_it) + { if (parentPath(child_it->first) == path) response.names.emplace_back(baseName(child_it->first)); + } response.stat = it->second.stat; response.error = Error::ZOK; } - return std::make_shared(response); + return { std::make_shared(response), {} }; } -ResponsePtr TestKeeperCheckRequest::process(TestKeeper::Container & container, int64_t) const +std::pair TestKeeperCheckRequest::process(TestKeeper::Container & container, int64_t) const { CheckResponse response; auto it = container.find(path); @@ -372,38 +412,42 @@ ResponsePtr TestKeeperCheckRequest::process(TestKeeper::Container & container, i response.error = Error::ZOK; } - return std::make_shared(response); + return { std::make_shared(response), {} }; } -ResponsePtr TestKeeperMultiRequest::process(TestKeeper::Container & container, int64_t zxid) const +std::pair TestKeeperMultiRequest::process(TestKeeper::Container & container, int64_t zxid) const { MultiResponse response; response.responses.reserve(requests.size()); - - /// Fairly inefficient. - auto container_copy = container; + std::vector undo_actions; try { for (const auto & request : requests) { const TestKeeperRequest & concrete_request = dynamic_cast(*request); - auto cur_response = concrete_request.process(container, zxid); + auto [ cur_response, undo_action ] = concrete_request.process(container, zxid); response.responses.emplace_back(cur_response); if (cur_response->error != Error::ZOK) { response.error = cur_response->error; - container = container_copy; - return std::make_shared(response); + + for (auto it = undo_actions.rbegin(); it != undo_actions.rend(); ++it) + (*it)(); + + return { std::make_shared(response), {} }; } + else + undo_actions.emplace_back(std::move(undo_action)); } response.error = Error::ZOK; - return std::make_shared(response); + return { std::make_shared(response), {} }; } catch (...) { - container = container_copy; + for (auto it = undo_actions.rbegin(); it != undo_actions.rend(); ++it) + (*it)(); throw; } } @@ -476,7 +520,7 @@ void TestKeeper::processingThread() ++zxid; info.request->addRootPath(root_path); - ResponsePtr response = info.request->process(container, zxid); + auto [response, _] = info.request->process(container, zxid); if (response->error == Error::ZOK) info.request->processWatches(watches, list_watches); From 43ba417132ddf7a3068a22b8d6f3b245eff7676c Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 11:34:38 +0300 Subject: [PATCH 083/143] Better submodules update --- docker/test/fasttest/run.sh | 40 ++----------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 4fa13ed3730..fc21fca990b 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -24,45 +24,9 @@ else fi fi -git submodule update --init --recursive contrib/boost | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt +SUBMODULES_TO_UPDATE="contrib/boost contrib/zlib-ng contrib/libxml2 contrib/poco contrib/libunwind contrib/ryu contrib/fmtlib contrib/base64 contrib/cctz contrib/libcpuid contrib/replxx contrib/double-conversion contrib/libcxx contrib/libcxxabi contrib/libc-headers contrib/lz4 contrib/zstd contrib/fastops contrib/rapidjson contrib/re2 contrib/sparsehash-c11" -git submodule update --init --recursive contrib/zlib-ng | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/libxml2 | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/poco | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/libunwind | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/ryu | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/fmtlib | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/cctz | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/libcpuid | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/replxx | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/double-conversion | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/libcxx | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/libcxxabi | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/libc-headers | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/lz4 | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/zstd | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/fastops | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/rapidjson | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/re2 | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt - -git submodule update --init --recursive contrib/sparsehash-c11 | ts '%Y-%m-%d %H:%M:%S' | tee -a /test_output/submodule_log.txt +git submodule update --init --recursive $SUBMODULES_TO_UPDATE | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -DENABLE_CAPNP=0 -DENABLE_RDKAFKA=0 -DENABLE_ICU=0 -DENABLE_POCO_NETSSL=0 -DENABLE_ODBC=0 -DENABLE_MYSQL=0 -DENABLE_SSL=0 -DENABLE_POCO_NETSSL=0 -DENABLE_CASSANDRA=0 -DENABLE_PARQUET=0 -DENABLE_AVRO=0 -DENABLE_EMBEDDED_COMPILER=0 -DENABLE_PROTOBUF=0 -DENABLE_H3=0 -DENABLE_TESTS=0 -DENABLE_UTILS=0 -DENABLE_ODBC=0 -DENABLE_GSASL_LIBRARY=0 -DENABLE_THINLTO=0 -DENABLE_MSGPACK=0 -DENABLE_LDAP=0 -DUSE_SNAPPY=0 -DENABLE_HYPERSCAN=0" From ecea1e02929b06f6ad9af235974e566a52792c1b Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 11:49:50 +0300 Subject: [PATCH 084/143] Run tests in parallel --- docker/test/fasttest/run.sh | 2 +- tests/clickhouse-test | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index fc21fca990b..37eaedc86ac 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -92,6 +92,6 @@ done TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close" -clickhouse-test --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt +clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt mv /var/log/clickhouse-server/* /test_output diff --git a/tests/clickhouse-test b/tests/clickhouse-test index 07fe681c2c8..5a721c196b0 100755 --- a/tests/clickhouse-test +++ b/tests/clickhouse-test @@ -598,16 +598,14 @@ def main(args): if jobs > run_total: run_total = jobs + batch_size = len(all_tests) / jobs all_tests_array = [] - for n in range(1, 1 + int(run_total)): - start = int(tests_n / run_total * (n - 1)) - end = int(tests_n / run_total * n) - all_tests_array.append([all_tests[start : end], suite, suite_dir, suite_tmp_dir, run_total]) + for i in range(0, len(all_tests), batch_size): + all_tests_array.append((all_tests[i:i+batch_size], suite, suite_dir, suite_tmp_dir, run_total)) if jobs > 1: with closing(multiprocessing.Pool(processes=jobs)) as pool: pool.map(run_tests_array, all_tests_array) - pool.terminate() else: run_tests_array(all_tests_array[int(run_n)-1]) From a061418dab768f4aefd27ad07484437383cc8fa0 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 12:23:50 +0300 Subject: [PATCH 085/143] Remove redundant cmd --- docker/test/stress/run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/test/stress/run.sh b/docker/test/stress/run.sh index ae7bbee7939..6669f8dd179 100755 --- a/docker/test/stress/run.sh +++ b/docker/test/stress/run.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -x + dpkg -i package_folder/clickhouse-common-static_*.deb dpkg -i package_folder/clickhouse-common-static-dbg_*.deb dpkg -i package_folder/clickhouse-server_*.deb @@ -52,5 +54,3 @@ service clickhouse-server restart wait_server clickhouse-client --query "SELECT 'Server successfuly started'" > /test_output/alive_check.txt || echo 'Server failed to start' > /test_output/alive_check.txt - -mv /var/log/clickhouse-server/* /test_output From 530ad951bcebfb7da559299a08faf5dd65916de1 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 12:29:31 +0300 Subject: [PATCH 086/143] Less tests --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 37eaedc86ac..eb4b6ad3ff0 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -90,7 +90,7 @@ do sleep 0.1 done -TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close" +TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter" clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt From 46991b8c6613190b908715bc56ff2f709f4b70d5 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 12:59:45 +0300 Subject: [PATCH 087/143] Flush stdout in tests --- tests/clickhouse-test | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/clickhouse-test b/tests/clickhouse-test index 5a721c196b0..12629628007 100755 --- a/tests/clickhouse-test +++ b/tests/clickhouse-test @@ -202,9 +202,8 @@ def run_tests_array(all_tests_with_params): (name, ext) = os.path.splitext(case) try: + sys.stdout.flush() sys.stdout.write("{0:72}".format(name + ": ")) - if run_total == 1: - sys.stdout.flush() if args.skip and any(s in name for s in args.skip): print(MSG_SKIPPED + " - skip") From f8229e0bf7edabc808a61bc9075795de534a4361 Mon Sep 17 00:00:00 2001 From: Artem Zuikov Date: Wed, 15 Jul 2020 13:08:40 +0300 Subject: [PATCH 088/143] try fix test --- tests/queries/0_stateless/01391_join_on_dict_crash.sql | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/queries/0_stateless/01391_join_on_dict_crash.sql b/tests/queries/0_stateless/01391_join_on_dict_crash.sql index 03d98e0cdda..998e0e21745 100644 --- a/tests/queries/0_stateless/01391_join_on_dict_crash.sql +++ b/tests/queries/0_stateless/01391_join_on_dict_crash.sql @@ -12,15 +12,16 @@ CREATE TABLE d_src (id UInt64, country_id UInt8, name String) Engine = Memory; INSERT INTO t VALUES (0, 0); INSERT INTO d_src VALUES (0, 0, 'n'); -CREATE DICTIONARY d (id UInt32, country_id UInt8, name String) PRIMARY KEY id -SOURCE(CLICKHOUSE(host 'localhost' port 9000 user 'default' password '' db 'db_01391' table 'd_src')) -LIFETIME(MIN 300 MAX 360) +CREATE DICTIONARY d (id UInt32, country_id UInt8, name String) +PRIMARY KEY id +SOURCE(CLICKHOUSE(HOST 'localhost' PORT 9000 USER 'default' DB 'db_01391' table 'd_src')) +LIFETIME(MIN 1 MAX 1) LAYOUT(HASHED()); select click_country_id from t cc left join d on toUInt32(d.id) = cc.click_city_id; +DROP DICTIONARY d; DROP TABLE t; DROP TABLE d_src; -DROP DICTIONARY d; DROP DATABASE IF EXISTS db_01391; From 5f01a587f6c6cc2b3c5bd1711a1187b4a89d967e Mon Sep 17 00:00:00 2001 From: Artem Zuikov Date: Wed, 15 Jul 2020 13:10:21 +0300 Subject: [PATCH 089/143] Optimize monotonous ORDER BY (#12467) --- src/Core/Settings.h | 1 + src/Interpreters/MonotonicityCheckVisitor.h | 142 +++++++++++++++ src/Interpreters/SyntaxAnalyzer.cpp | 45 +++++ tests/performance/monotonous_order_by.xml | 9 + ...monotonous_functions_in_order_by.reference | 168 ++++++++++++++++++ ...01321_monotonous_functions_in_order_by.sql | 59 ++++++ ...rder_by_with_different_variables.reference | 32 ++++ ...nous_order_by_with_different_variables.sql | 21 +++ 8 files changed, 477 insertions(+) create mode 100644 src/Interpreters/MonotonicityCheckVisitor.h create mode 100644 tests/performance/monotonous_order_by.xml create mode 100644 tests/queries/0_stateless/01321_monotonous_functions_in_order_by.reference create mode 100644 tests/queries/0_stateless/01321_monotonous_functions_in_order_by.sql create mode 100644 tests/queries/0_stateless/01322_monotonous_order_by_with_different_variables.reference create mode 100644 tests/queries/0_stateless/01322_monotonous_order_by_with_different_variables.sql diff --git a/src/Core/Settings.h b/src/Core/Settings.h index 21650b0c6fa..dbae8bdb978 100644 --- a/src/Core/Settings.h +++ b/src/Core/Settings.h @@ -372,6 +372,7 @@ struct Settings : public SettingsCollection M(SettingBool, optimize_duplicate_order_by_and_distinct, true, "Remove duplicate ORDER BY and DISTINCT if it's possible", 0) \ M(SettingBool, optimize_redundant_functions_in_order_by, true, "Remove functions from ORDER BY if its argument is also in ORDER BY", 0) \ M(SettingBool, optimize_if_chain_to_multiif, false, "Replace if(cond1, then1, if(cond2, ...)) chains to multiIf. Currently it's not beneficial for numeric types.", 0) \ + M(SettingBool, optimize_monotonous_functions_in_order_by, true, "Replace monotonous function with its argument in ORDER BY", 0) \ M(SettingBool, allow_experimental_alter_materialized_view_structure, false, "Allow atomic alter on Materialized views. Work in progress.", 0) \ M(SettingBool, enable_early_constant_folding, true, "Enable query optimization where we analyze function and subqueries results and rewrite query if there're constants there", 0) \ \ diff --git a/src/Interpreters/MonotonicityCheckVisitor.h b/src/Interpreters/MonotonicityCheckVisitor.h new file mode 100644 index 00000000000..d813f9618e1 --- /dev/null +++ b/src/Interpreters/MonotonicityCheckVisitor.h @@ -0,0 +1,142 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace DB +{ + +using Monotonicity = IFunctionBase::Monotonicity; + +/// Checks from bottom to top if function composition is monotonous +class MonotonicityCheckMatcher +{ +public: + struct Data + { + const TablesWithColumns & tables; + const Context & context; + const std::unordered_set & group_by_function_hashes; + Monotonicity monotonicity{true, true, true}; + ASTIdentifier * identifier = nullptr; + DataTypePtr arg_data_type = {}; + + void reject() { monotonicity.is_monotonic = false; } + bool isRejected() const { return !monotonicity.is_monotonic; } + + bool canOptimize(const ASTFunction & ast_function) const + { + /// if GROUP BY contains the same function ORDER BY shouldn't be optimized + auto hash = ast_function.getTreeHash(); + String key = toString(hash.first) + '_' + toString(hash.second); + if (group_by_function_hashes.count(key)) + return false; + + /// if ORDER BY contains aggregate function it shouldn't be optimized + if (AggregateFunctionFactory::instance().isAggregateFunctionName(ast_function.name)) + return false; + + return true; + } + + bool extractIdentifierAndType(const ASTFunction & ast_function) + { + if (identifier) + return true; + + identifier = ast_function.arguments->children[0]->as(); + if (!identifier) + return false; + + auto pos = IdentifierSemantic::getMembership(*identifier); + if (!pos) + pos = IdentifierSemantic::chooseTableColumnMatch(*identifier, tables, true); + if (!pos) + return false; + + if (auto data_type_and_name = tables[*pos].columns.tryGetByName(identifier->shortName())) + { + arg_data_type = data_type_and_name->type; + return true; + } + + return false; + } + }; + + static void visit(const ASTPtr & ast, Data & data) + { + if (const auto * ast_function = ast->as()) + visit(*ast_function, data); + } + + static void visit(const ASTFunction & ast_function, Data & data) + { + if (data.isRejected()) + return; + + /// TODO: monotonicity for fucntions of several arguments + auto arguments = ast_function.arguments; + if (arguments->children.size() != 1) + { + data.reject(); + return; + } + + if (!data.canOptimize(ast_function)) + { + data.reject(); + return; + } + + const auto & function = FunctionFactory::instance().tryGet(ast_function.name, data.context); + if (!function) + { + data.reject(); + return; + } + + /// First time extract the most enclosed identifier and its data type + if (!data.arg_data_type && !data.extractIdentifierAndType(ast_function)) + { + data.reject(); + return; + } + + ColumnsWithTypeAndName args; + args.emplace_back(data.arg_data_type, "tmp"); + auto function_base = function->build(args); + + if (function_base && function_base->hasInformationAboutMonotonicity()) + { + bool is_positive = data.monotonicity.is_positive; + data.monotonicity = function_base->getMonotonicityForRange(*data.arg_data_type, Field(), Field()); + + if (!is_positive) + data.monotonicity.is_positive = !data.monotonicity.is_positive; + data.arg_data_type = function_base->getReturnType(); + } + else + data.reject(); + } + + static bool needChildVisit(const ASTPtr &, const ASTPtr &) + { + return true; + } +}; + +using MonotonicityCheckVisitor = ConstInDepthNodeVisitor; + +} diff --git a/src/Interpreters/SyntaxAnalyzer.cpp b/src/Interpreters/SyntaxAnalyzer.cpp index 0579e0c215b..7decc000b34 100644 --- a/src/Interpreters/SyntaxAnalyzer.cpp +++ b/src/Interpreters/SyntaxAnalyzer.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -529,6 +530,46 @@ void optimizeDuplicateOrderByAndDistinct(ASTPtr & query, const Context & context DuplicateDistinctVisitor(distinct_data).visit(query); } +/// Replace monotonous functions in ORDER BY if they don't participate in GROUP BY expression, +/// has a single argument and not an aggregate functions. +void optimizeMonotonousFunctionsInOrderBy(ASTSelectQuery * select_query, const Context & context, + const TablesWithColumns & tables_with_columns) +{ + auto order_by = select_query->orderBy(); + if (!order_by) + return; + + std::unordered_set group_by_hashes; + if (auto group_by = select_query->groupBy()) + { + for (auto & elem : group_by->children) + { + auto hash = elem->getTreeHash(); + String key = toString(hash.first) + '_' + toString(hash.second); + group_by_hashes.insert(key); + } + } + + for (auto & child : order_by->children) + { + auto * order_by_element = child->as(); + auto & ast_func = order_by_element->children[0]; + if (!ast_func->as()) + continue; + + MonotonicityCheckVisitor::Data data{tables_with_columns, context, group_by_hashes}; + MonotonicityCheckVisitor(data).visit(ast_func); + + if (!data.isRejected()) + { + ast_func = data.identifier->clone(); + ast_func->setAlias(""); + if (!data.monotonicity.is_positive) + order_by_element->direction *= -1; + } + } +} + /// If ORDER BY has argument x followed by f(x) transfroms it to ORDER BY x. /// Optimize ORDER BY x, y, f(x), g(x, y), f(h(x)), t(f(x), g(x)) into ORDER BY x, y /// in case if f(), g(), h(), t() are deterministic (in scope of query). @@ -1066,6 +1107,10 @@ SyntaxAnalyzerResultPtr SyntaxAnalyzer::analyzeSelect( if (settings.optimize_redundant_functions_in_order_by) optimizeRedundantFunctionsInOrderBy(select_query, context); + /// Replace monotonous functions with its argument + if (settings.optimize_monotonous_functions_in_order_by) + optimizeMonotonousFunctionsInOrderBy(select_query, context, tables_with_columns); + /// Remove duplicated elements from LIMIT BY clause. optimizeLimitBy(select_query); diff --git a/tests/performance/monotonous_order_by.xml b/tests/performance/monotonous_order_by.xml new file mode 100644 index 00000000000..1c58c4e9d0a --- /dev/null +++ b/tests/performance/monotonous_order_by.xml @@ -0,0 +1,9 @@ + + + hits_10m_single + + + SELECT * FROM (SELECT CounterID, EventDate FROM hits_10m_single) ORDER BY toFloat32(toFloat64(toFloat32(toFloat64(CounterID)))) FORMAT Null + SELECT * FROM (SELECT CounterID, EventDate FROM hits_10m_single) ORDER BY toFloat32(toFloat64(toFloat32(toFloat64(CounterID)))) DESC, toFloat32(toFloat64(toFloat32(toFloat64(EventDate)))) ASC FORMAT Null + + diff --git a/tests/queries/0_stateless/01321_monotonous_functions_in_order_by.reference b/tests/queries/0_stateless/01321_monotonous_functions_in_order_by.reference new file mode 100644 index 00000000000..e8e7d754ed9 --- /dev/null +++ b/tests/queries/0_stateless/01321_monotonous_functions_in_order_by.reference @@ -0,0 +1,168 @@ +0 +1 +2 +0 +1 +2 +0 +1 +2 +2 +1 +0 +0 +1 +2 +0 +1 +2 +0 +1 +2 +2 +1 +0 +2 +1 +0 +2 +1 +0 +0 +1 +2 +2 +1 +0 +2 +1 +0 +SELECT number +FROM numbers(3) +ORDER BY number ASC +SELECT number +FROM numbers(3) +ORDER BY abs(toFloat32(number)) ASC +SELECT number +FROM numbers(3) +ORDER BY toFloat32(abs(number)) ASC +SELECT number +FROM numbers(3) +ORDER BY number DESC +SELECT number +FROM numbers(3) +ORDER BY exp(number) ASC +SELECT roundToExp2(number) AS x +FROM numbers(3) +ORDER BY + number ASC, + number ASC +SELECT number AS x +FROM numbers(3) +ORDER BY + number ASC, + number ASC +SELECT number +FROM numbers(3) +ORDER BY number DESC +SELECT number +FROM numbers(3) +ORDER BY abs(toFloat32(number)) DESC +SELECT number +FROM numbers(3) +ORDER BY toFloat32(abs(number)) DESC +SELECT number +FROM numbers(3) +ORDER BY number ASC +SELECT number +FROM numbers(3) +ORDER BY exp(number) DESC +SELECT roundToExp2(number) AS x +FROM numbers(3) +ORDER BY + number DESC, + number DESC +0 +1 +2 +0 +1 +2 +0 +1 +2 +2 +1 +0 +0 +1 +2 +0 +1 +2 +0 +1 +2 +2 +1 +0 +2 +1 +0 +2 +1 +0 +0 +1 +2 +2 +1 +0 +2 +1 +0 +SELECT number +FROM numbers(3) +ORDER BY toFloat32(toFloat64(number)) ASC +SELECT number +FROM numbers(3) +ORDER BY abs(toFloat32(number)) ASC +SELECT number +FROM numbers(3) +ORDER BY toFloat32(abs(number)) ASC +SELECT number +FROM numbers(3) +ORDER BY -number ASC +SELECT number +FROM numbers(3) +ORDER BY exp(number) ASC +SELECT roundToExp2(number) AS x +FROM numbers(3) +ORDER BY + x ASC, + toFloat32(x) ASC +SELECT number AS x +FROM numbers(3) +ORDER BY + toFloat32(x) AS k ASC, + toFloat64(k) ASC +SELECT number +FROM numbers(3) +ORDER BY toFloat32(toFloat64(number)) DESC +SELECT number +FROM numbers(3) +ORDER BY abs(toFloat32(number)) DESC +SELECT number +FROM numbers(3) +ORDER BY toFloat32(abs(number)) DESC +SELECT number +FROM numbers(3) +ORDER BY -number DESC +SELECT number +FROM numbers(3) +ORDER BY exp(number) DESC +SELECT roundToExp2(number) AS x +FROM numbers(3) +ORDER BY + x DESC, + toFloat32(x) DESC diff --git a/tests/queries/0_stateless/01321_monotonous_functions_in_order_by.sql b/tests/queries/0_stateless/01321_monotonous_functions_in_order_by.sql new file mode 100644 index 00000000000..7f4b5881104 --- /dev/null +++ b/tests/queries/0_stateless/01321_monotonous_functions_in_order_by.sql @@ -0,0 +1,59 @@ +SET enable_debug_queries = 1; +SET optimize_monotonous_functions_in_order_by = 1; + +SELECT number FROM numbers(3) ORDER BY toFloat32(toFloat64(number)); +SELECT number FROM numbers(3) ORDER BY abs(toFloat32(number)); +SELECT number FROM numbers(3) ORDER BY toFloat32(abs(number)); +SELECT number FROM numbers(3) ORDER BY -number; +SELECT number FROM numbers(3) ORDER BY exp(number); +SELECT roundToExp2(number) AS x FROM numbers(3) ORDER BY x, toFloat32(x); +SELECT number AS x FROM numbers(3) ORDER BY toFloat32(x) as k, toFloat64(k); +SELECT number FROM numbers(3) ORDER BY toFloat32(toFloat64(number)) DESC; +SELECT number FROM numbers(3) ORDER BY abs(toFloat32(number)) DESC; +SELECT number FROM numbers(3) ORDER BY toFloat32(abs(number)) DESC; +SELECT number FROM numbers(3) ORDER BY -number DESC; +SELECT number FROM numbers(3) ORDER BY exp(number) DESC; +SELECT roundToExp2(number) AS x FROM numbers(3) ORDER BY x DESC, toFloat32(x) DESC; +analyze SELECT number FROM numbers(3) ORDER BY toFloat32(toFloat64(number)); +analyze SELECT number FROM numbers(3) ORDER BY abs(toFloat32(number)); +analyze SELECT number FROM numbers(3) ORDER BY toFloat32(abs(number)); +analyze SELECT number FROM numbers(3) ORDER BY -number; +analyze SELECT number FROM numbers(3) ORDER BY exp(number); +analyze SELECT roundToExp2(number) AS x FROM numbers(3) ORDER BY x, toFloat32(x); +analyze SELECT number AS x FROM numbers(3) ORDER BY toFloat32(x) as k, toFloat64(k); +analyze SELECT number FROM numbers(3) ORDER BY toFloat32(toFloat64(number)) DESC; +analyze SELECT number FROM numbers(3) ORDER BY abs(toFloat32(number)) DESC; +analyze SELECT number FROM numbers(3) ORDER BY toFloat32(abs(number)) DESC; +analyze SELECT number FROM numbers(3) ORDER BY -number DESC; +analyze SELECT number FROM numbers(3) ORDER BY exp(number) DESC; +analyze SELECT roundToExp2(number) AS x FROM numbers(3) ORDER BY x DESC, toFloat32(x) DESC; + +SET optimize_monotonous_functions_in_order_by = 0; + +SELECT number FROM numbers(3) ORDER BY toFloat32(toFloat64(number)); +SELECT number FROM numbers(3) ORDER BY abs(toFloat32(number)); +SELECT number FROM numbers(3) ORDER BY toFloat32(abs(number)); +SELECT number FROM numbers(3) ORDER BY -number; +SELECT number FROM numbers(3) ORDER BY exp(number); +SELECT roundToExp2(number) AS x FROM numbers(3) ORDER BY x, toFloat32(x); +SELECT number AS x FROM numbers(3) ORDER BY toFloat32(x) as k, toFloat64(k); +SELECT number FROM numbers(3) ORDER BY toFloat32(toFloat64(number)) DESC; +SELECT number FROM numbers(3) ORDER BY abs(toFloat32(number)) DESC; +SELECT number FROM numbers(3) ORDER BY toFloat32(abs(number)) DESC; +SELECT number FROM numbers(3) ORDER BY -number DESC; +SELECT number FROM numbers(3) ORDER BY exp(number) DESC; +SELECT roundToExp2(number) AS x FROM numbers(3) ORDER BY x DESC, toFloat32(x) DESC; +analyze SELECT number FROM numbers(3) ORDER BY toFloat32(toFloat64(number)); +analyze SELECT number FROM numbers(3) ORDER BY abs(toFloat32(number)); +analyze SELECT number FROM numbers(3) ORDER BY toFloat32(abs(number)); +analyze SELECT number FROM numbers(3) ORDER BY -number; +analyze SELECT number FROM numbers(3) ORDER BY exp(number); +analyze SELECT roundToExp2(number) AS x FROM numbers(3) ORDER BY x, toFloat32(x); +analyze SELECT number AS x FROM numbers(3) ORDER BY toFloat32(x) as k, toFloat64(k); +analyze SELECT number FROM numbers(3) ORDER BY toFloat32(toFloat64(number)) DESC; +analyze SELECT number FROM numbers(3) ORDER BY abs(toFloat32(number)) DESC; +analyze SELECT number FROM numbers(3) ORDER BY toFloat32(abs(number)) DESC; +analyze SELECT number FROM numbers(3) ORDER BY -number DESC; +analyze SELECT number FROM numbers(3) ORDER BY exp(number) DESC; +analyze SELECT roundToExp2(number) AS x FROM numbers(3) ORDER BY x DESC, toFloat32(x) DESC; +-- TODO: exp() should be monotonous function diff --git a/tests/queries/0_stateless/01322_monotonous_order_by_with_different_variables.reference b/tests/queries/0_stateless/01322_monotonous_order_by_with_different_variables.reference new file mode 100644 index 00000000000..cf2935a40bf --- /dev/null +++ b/tests/queries/0_stateless/01322_monotonous_order_by_with_different_variables.reference @@ -0,0 +1,32 @@ +1 4 3 +1 3 3 +2 5 4 +2 2 4 +1 3 3 +1 4 3 +2 2 4 +2 5 4 +2 +1 +2 +1 3 3 +1 4 3 +2 5 4 +2 2 4 +2 +1 4 3 +1 3 3 +2 5 4 +2 2 4 +1 3 3 +1 4 3 +2 2 4 +2 5 4 +2 +1 +2 +1 3 3 +1 4 3 +2 5 4 +2 2 4 +2 diff --git a/tests/queries/0_stateless/01322_monotonous_order_by_with_different_variables.sql b/tests/queries/0_stateless/01322_monotonous_order_by_with_different_variables.sql new file mode 100644 index 00000000000..6fda42cbed1 --- /dev/null +++ b/tests/queries/0_stateless/01322_monotonous_order_by_with_different_variables.sql @@ -0,0 +1,21 @@ +DROP TABLE IF EXISTS test; +CREATE TABLE test (x Int8, y Int8, z Int8) ENGINE = MergeTree ORDER BY tuple(); +INSERT INTO test VALUES (1, 3, 3), (1, 4, 3), (2, 5, 4), (2, 2, 4); + +SET optimize_monotonous_functions_in_order_by = 1; +SELECT * FROM test ORDER BY toFloat32(x), -y, -z DESC; +SELECT * FROM test ORDER BY toFloat32(x), -(-y), -z DESC; +SELECT max(x) as k FROM test ORDER BY k; +SELECT roundToExp2(x) as k FROM test GROUP BY k ORDER BY k; +SELECT roundToExp2(x) as k, y, z FROM test WHERE k >= 1 ORDER BY k; +SELECT max(x) as k FROM test HAVING k > 0 ORDER BY k; + +SET optimize_monotonous_functions_in_order_by = 0; +SELECT * FROM test ORDER BY toFloat32(x), -y, -z DESC; +SELECT * FROM test ORDER BY toFloat32(x), -(-y), -z DESC; +SELECT max(x) as k FROM test ORDER BY k; +SELECT roundToExp2(x) as k From test GROUP BY k ORDER BY k; +SELECT roundToExp2(x) as k, y, z FROM test WHERE k >= 1 ORDER BY k; +SELECT max(x) as k FROM test HAVING k > 0 ORDER BY k; + +DROP TABLE test; From fbd80e8d672e450e10d92d26cdb44871353e5d3f Mon Sep 17 00:00:00 2001 From: Anton Ivashkin Date: Wed, 15 Jul 2020 14:15:12 +0300 Subject: [PATCH 090/143] Fix codestyle --- src/IO/ReadBufferFromS3.cpp | 2 +- src/IO/S3/PocoHTTPClient.cpp | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/IO/ReadBufferFromS3.cpp b/src/IO/ReadBufferFromS3.cpp index 3287609d3d4..fd07a7f309a 100644 --- a/src/IO/ReadBufferFromS3.cpp +++ b/src/IO/ReadBufferFromS3.cpp @@ -43,7 +43,7 @@ bool ReadBufferFromS3::nextImpl() initialized = true; } - Stopwatch watch(CLOCK_MONOTONIC); + Stopwatch watch; auto res = impl->next(); watch.stop(); ProfileEvents::increment(ProfileEvents::S3ReadMicroseconds, watch.elapsedMicroseconds()); diff --git a/src/IO/S3/PocoHTTPClient.cpp b/src/IO/S3/PocoHTTPClient.cpp index 39f879beaf4..efa402c9447 100644 --- a/src/IO/S3/PocoHTTPClient.cpp +++ b/src/IO/S3/PocoHTTPClient.cpp @@ -79,7 +79,7 @@ void PocoHTTPClient::MakeRequestInternal( auto uri = request.GetUri().GetURIString(); LOG_DEBUG(log, "Make request to: {}", uri); - enum class ES3MetricType + enum class S3MetricType { Microseconds, Count, @@ -90,7 +90,7 @@ void PocoHTTPClient::MakeRequestInternal( EnumSize, }; - auto SelectMetric = [&request](ES3MetricType type) + auto selectMetric = [&request](S3MetricType type) { const ProfileEvents::Event events_map[][2] = { {ProfileEvents::S3ReadMicroseconds, ProfileEvents::S3WriteMicroseconds}, @@ -100,7 +100,7 @@ void PocoHTTPClient::MakeRequestInternal( {ProfileEvents::S3ReadRequestsRedirects, ProfileEvents::S3WriteRequestsRedirects}, }; - static_assert((sizeof(events_map) / sizeof(events_map[0])) == static_cast(ES3MetricType::EnumSize)); + static_assert((sizeof(events_map) / sizeof(events_map[0])) == static_cast(S3MetricType::EnumSize)); switch (request.GetMethod()) { @@ -114,10 +114,10 @@ void PocoHTTPClient::MakeRequestInternal( return events_map[static_cast(type)][1]; // Write } - throw Exception(String("Unsupported request method"), ErrorCodes::NOT_IMPLEMENTED); + throw Exception("Unsupported request method", ErrorCodes::NOT_IMPLEMENTED); }; - ProfileEvents::increment(SelectMetric(ES3MetricType::Count)); + ProfileEvents::increment(selectMetric(S3MetricType::Count)); const int MAX_REDIRECT_ATTEMPTS = 10; try @@ -170,7 +170,7 @@ void PocoHTTPClient::MakeRequestInternal( Poco::Net::HTTPResponse poco_response; - Stopwatch watch(CLOCK_MONOTONIC); + Stopwatch watch; auto & request_body_stream = session->sendRequest(poco_request); @@ -191,7 +191,7 @@ void PocoHTTPClient::MakeRequestInternal( auto & response_body_stream = session->receiveResponse(poco_response); watch.stop(); - ProfileEvents::increment(SelectMetric(ES3MetricType::Microseconds), watch.elapsedMicroseconds()); + ProfileEvents::increment(selectMetric(S3MetricType::Microseconds), watch.elapsedMicroseconds()); int status_code = static_cast(poco_response.getStatus()); LOG_DEBUG(log, "Response status: {}, {}", status_code, poco_response.getReason()); @@ -202,7 +202,7 @@ void PocoHTTPClient::MakeRequestInternal( uri = location; LOG_DEBUG(log, "Redirecting request to new location: {}", location); - ProfileEvents::increment(SelectMetric(ES3MetricType::Redirects)); + ProfileEvents::increment(selectMetric(S3MetricType::Redirects)); continue; } @@ -228,11 +228,11 @@ void PocoHTTPClient::MakeRequestInternal( if (status_code == 429 || status_code == 503) { // API throttling - ProfileEvents::increment(SelectMetric(ES3MetricType::Throttling)); + ProfileEvents::increment(selectMetric(S3MetricType::Throttling)); } else { - ProfileEvents::increment(SelectMetric(ES3MetricType::Errors)); + ProfileEvents::increment(selectMetric(S3MetricType::Errors)); } } else @@ -249,7 +249,7 @@ void PocoHTTPClient::MakeRequestInternal( response->SetClientErrorType(Aws::Client::CoreErrors::NETWORK_CONNECTION); response->SetClientErrorMessage(getCurrentExceptionMessage(false)); - ProfileEvents::increment(SelectMetric(ES3MetricType::Errors)); + ProfileEvents::increment(selectMetric(S3MetricType::Errors)); } } } From 3e6b9f297fed35185e4fa98eae7bbe05502693ad Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Wed, 15 Jul 2020 14:16:00 +0300 Subject: [PATCH 091/143] Some provisions for Android build --- CMakeLists.txt | 2 +- base/common/getThreadId.cpp | 9 ++++++-- base/daemon/BaseDaemon.cpp | 1 - cmake/find/amqpcpp.cmake | 2 +- cmake/linux/default_libs.cmake | 11 +++++++++- cmake/target.cmake | 7 +++++- src/Common/MemoryStatisticsOS.cpp | 4 ++++ src/Common/MemoryStatisticsOS.h | 3 +++ src/Dictionaries/SSDCacheDictionary.cpp | 2 +- .../SSDComplexKeyCacheDictionary.cpp | 2 +- .../SSDComplexKeyCacheDictionary.h | 2 +- src/Dictionaries/registerDictionaries.cpp | 2 +- src/Functions/FunctionsExternalDictionaries.h | 22 +++++++++---------- src/IO/AIOContextPool.cpp | 2 +- src/IO/AIOContextPool.h | 2 +- src/IO/BitHelpers.h | 2 +- src/IO/ReadBufferAIO.cpp | 2 +- src/IO/ReadBufferAIO.h | 2 +- src/IO/WriteBufferAIO.cpp | 2 +- src/IO/WriteBufferAIO.h | 2 +- src/IO/createReadBufferFromFileBase.cpp | 4 ++-- src/IO/createWriteBufferFromFileBase.cpp | 4 ++-- 22 files changed, 58 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c213ace742..1153f418056 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -287,7 +287,7 @@ endif () include(cmake/dbms_glob_sources.cmake) -if (OS_LINUX) +if (OS_LINUX OR OS_ANDROID) include(cmake/linux/default_libs.cmake) elseif (OS_DARWIN) include(cmake/darwin/default_libs.cmake) diff --git a/base/common/getThreadId.cpp b/base/common/getThreadId.cpp index 2575aba3844..700c51f21fc 100644 --- a/base/common/getThreadId.cpp +++ b/base/common/getThreadId.cpp @@ -1,6 +1,9 @@ #include -#if defined(OS_LINUX) +#if defined(OS_ANDROID) + #include + #include +#elif defined(OS_LINUX) #include #include #elif defined(OS_FREEBSD) @@ -16,7 +19,9 @@ uint64_t getThreadId() { if (!current_tid) { -#if defined(OS_LINUX) +#if defined(OS_ANDROID) + current_tid = gettid(); +#elif defined(OS_LINUX) current_tid = syscall(SYS_gettid); /// This call is always successful. - man gettid #elif defined(OS_FREEBSD) current_tid = pthread_getthreadid_np(); diff --git a/base/daemon/BaseDaemon.cpp b/base/daemon/BaseDaemon.cpp index c0f454107ab..e9f85da3594 100644 --- a/base/daemon/BaseDaemon.cpp +++ b/base/daemon/BaseDaemon.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include diff --git a/cmake/find/amqpcpp.cmake b/cmake/find/amqpcpp.cmake index 0868e76c28a..5d66e3a41b1 100644 --- a/cmake/find/amqpcpp.cmake +++ b/cmake/find/amqpcpp.cmake @@ -1,4 +1,4 @@ -SET(ENABLE_AMQPCPP ${ENABLE_LIBRARIES}) +option(ENABLE_AMQPCPP "Enalbe AMQP-CPP" ${ENABLE_LIBRARIES}) if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/AMQP-CPP/CMakeLists.txt") message (WARNING "submodule contrib/AMQP-CPP is missing. to fix try run: \n git submodule update --init --recursive") set (ENABLE_AMQPCPP 0) diff --git a/cmake/linux/default_libs.cmake b/cmake/linux/default_libs.cmake index da91ccaa0c2..2a325b4d095 100644 --- a/cmake/linux/default_libs.cmake +++ b/cmake/linux/default_libs.cmake @@ -11,7 +11,12 @@ else () set (BUILTINS_LIBRARY "-lgcc") endif () +if (OS_ANDROID) +# pthread and rt are included in libc +set (DEFAULT_LIBS "${DEFAULT_LIBS} ${BUILTINS_LIBRARY} ${COVERAGE_OPTION} -lc -lm -ldl") +else () set (DEFAULT_LIBS "${DEFAULT_LIBS} ${BUILTINS_LIBRARY} ${COVERAGE_OPTION} -lc -lm -lrt -lpthread -ldl") +endif () message(STATUS "Default libraries: ${DEFAULT_LIBS}") @@ -35,7 +40,11 @@ add_library(global-libs INTERFACE) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) -add_subdirectory(base/glibc-compatibility) +if (NOT OS_ANDROID) + # Our compatibility layer doesn't build under Android, many errors in musl. + add_subdirectory(base/glibc-compatibility) +endif () + include (cmake/find/unwind.cmake) include (cmake/find/cxx.cmake) diff --git a/cmake/target.cmake b/cmake/target.cmake index 1325758811f..35040e48956 100644 --- a/cmake/target.cmake +++ b/cmake/target.cmake @@ -1,6 +1,11 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux") set (OS_LINUX 1) add_definitions(-D OS_LINUX) +elseif (CMAKE_SYSTEM_NAME MATCHES "Android") + # This is a toy configuration and not in CI, so expect it to be broken. + # Use cmake flags such as: -DCMAKE_TOOLCHAIN_FILE=~/ch2/android-ndk-r21d/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28 + set (OS_ANDROID 1) + add_definitions(-D OS_ANDROID) elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") set (OS_FREEBSD 1) add_definitions(-D OS_FREEBSD) @@ -17,7 +22,7 @@ if (CMAKE_CROSSCOMPILING) set (ENABLE_PARQUET OFF CACHE INTERNAL "") set (ENABLE_ICU OFF CACHE INTERNAL "") set (ENABLE_FASTOPS OFF CACHE INTERNAL "") - elseif (OS_LINUX) + elseif (OS_LINUX OR OS_ANDROID) if (ARCH_AARCH64) # FIXME: broken dependencies set (ENABLE_PROTOBUF OFF CACHE INTERNAL "") diff --git a/src/Common/MemoryStatisticsOS.cpp b/src/Common/MemoryStatisticsOS.cpp index 6082d23cbd0..7c65461aeb6 100644 --- a/src/Common/MemoryStatisticsOS.cpp +++ b/src/Common/MemoryStatisticsOS.cpp @@ -1,3 +1,5 @@ +#if defined(OS_LINUX) + #include #include #include @@ -101,3 +103,5 @@ MemoryStatisticsOS::Data MemoryStatisticsOS::get() const } } + +#endif diff --git a/src/Common/MemoryStatisticsOS.h b/src/Common/MemoryStatisticsOS.h index 97caf4e8fbe..1661b62711f 100644 --- a/src/Common/MemoryStatisticsOS.h +++ b/src/Common/MemoryStatisticsOS.h @@ -1,4 +1,5 @@ #pragma once +#if defined(OS_LINUX) #include @@ -38,3 +39,5 @@ private: }; } + +#endif diff --git a/src/Dictionaries/SSDCacheDictionary.cpp b/src/Dictionaries/SSDCacheDictionary.cpp index 2d6755a1759..6c789b255d3 100644 --- a/src/Dictionaries/SSDCacheDictionary.cpp +++ b/src/Dictionaries/SSDCacheDictionary.cpp @@ -1,4 +1,4 @@ -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include "SSDCacheDictionary.h" diff --git a/src/Dictionaries/SSDComplexKeyCacheDictionary.cpp b/src/Dictionaries/SSDComplexKeyCacheDictionary.cpp index bfd85378228..21fd4140f70 100644 --- a/src/Dictionaries/SSDComplexKeyCacheDictionary.cpp +++ b/src/Dictionaries/SSDComplexKeyCacheDictionary.cpp @@ -1,4 +1,4 @@ -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include "SSDComplexKeyCacheDictionary.h" diff --git a/src/Dictionaries/SSDComplexKeyCacheDictionary.h b/src/Dictionaries/SSDComplexKeyCacheDictionary.h index 9f89ecd0871..b9a8466d8c9 100644 --- a/src/Dictionaries/SSDComplexKeyCacheDictionary.h +++ b/src/Dictionaries/SSDComplexKeyCacheDictionary.h @@ -1,6 +1,6 @@ #pragma once -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include "DictionaryStructure.h" #include "IDictionary.h" diff --git a/src/Dictionaries/registerDictionaries.cpp b/src/Dictionaries/registerDictionaries.cpp index 1d3b48b21a9..b5e98db05b4 100644 --- a/src/Dictionaries/registerDictionaries.cpp +++ b/src/Dictionaries/registerDictionaries.cpp @@ -33,7 +33,7 @@ void registerDictionaries() registerDictionaryFlat(factory); registerDictionaryHashed(factory); registerDictionaryCache(factory); -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) registerDictionarySSDCache(factory); registerDictionarySSDComplexKeyCache(factory); #endif diff --git a/src/Functions/FunctionsExternalDictionaries.h b/src/Functions/FunctionsExternalDictionaries.h index 7f3979f2141..bace458b7da 100644 --- a/src/Functions/FunctionsExternalDictionaries.h +++ b/src/Functions/FunctionsExternalDictionaries.h @@ -29,7 +29,7 @@ #include #include #include -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include #include #endif @@ -182,13 +182,13 @@ private: !executeDispatchSimple(block, arguments, result, dict) && !executeDispatchSimple(block, arguments, result, dict) && !executeDispatchSimple(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatchSimple(block, arguments, result, dict) && #endif !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatchComplex(block, arguments, result, dict) && #endif #if !defined(ARCADIA_BUILD) @@ -338,13 +338,13 @@ private: !executeDispatch(block, arguments, result, dict) && !executeDispatch(block, arguments, result, dict) && !executeDispatch(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatch(block, arguments, result, dict) && #endif !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatchComplex(block, arguments, result, dict) && #endif #if !defined(ARCADIA_BUILD) @@ -522,13 +522,13 @@ private: !executeDispatch(block, arguments, result, dict) && !executeDispatch(block, arguments, result, dict) && !executeDispatch(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatch(block, arguments, result, dict) && #endif !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatchComplex(block, arguments, result, dict) && #endif #if !defined(ARCADIA_BUILD) @@ -862,13 +862,13 @@ private: !executeDispatch(block, arguments, result, dict) && !executeDispatch(block, arguments, result, dict) && !executeDispatch(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatch(block, arguments, result, dict) && #endif !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatchComplex(block, arguments, result, dict) && #endif #if !defined(ARCADIA_BUILD) @@ -1123,13 +1123,13 @@ private: !executeDispatch(block, arguments, result, dict) && !executeDispatch(block, arguments, result, dict) && !executeDispatch(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatch(block, arguments, result, dict) && #endif !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && !executeDispatchComplex(block, arguments, result, dict) && -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) !executeDispatchComplex(block, arguments, result, dict) && #endif #if !defined(ARCADIA_BUILD) diff --git a/src/IO/AIOContextPool.cpp b/src/IO/AIOContextPool.cpp index a06d76e86a2..eb9ee58b9e4 100644 --- a/src/IO/AIOContextPool.cpp +++ b/src/IO/AIOContextPool.cpp @@ -1,4 +1,4 @@ -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include #include diff --git a/src/IO/AIOContextPool.h b/src/IO/AIOContextPool.h index 15160bc7fb6..9f4047939f4 100644 --- a/src/IO/AIOContextPool.h +++ b/src/IO/AIOContextPool.h @@ -1,6 +1,6 @@ #pragma once -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include #include diff --git a/src/IO/BitHelpers.h b/src/IO/BitHelpers.h index 35fe630029c..05eac24f1b0 100644 --- a/src/IO/BitHelpers.h +++ b/src/IO/BitHelpers.h @@ -7,7 +7,7 @@ #include #include -#if defined(__OpenBSD__) || defined(__FreeBSD__) +#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined (__ANDROID__) # include #elif defined(__APPLE__) # include diff --git a/src/IO/ReadBufferAIO.cpp b/src/IO/ReadBufferAIO.cpp index 8b01b67c0c0..abf55021cfb 100644 --- a/src/IO/ReadBufferAIO.cpp +++ b/src/IO/ReadBufferAIO.cpp @@ -1,4 +1,4 @@ -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include #include diff --git a/src/IO/ReadBufferAIO.h b/src/IO/ReadBufferAIO.h index 5b2cf247a45..d476865747d 100644 --- a/src/IO/ReadBufferAIO.h +++ b/src/IO/ReadBufferAIO.h @@ -1,6 +1,6 @@ #pragma once -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include #include diff --git a/src/IO/WriteBufferAIO.cpp b/src/IO/WriteBufferAIO.cpp index c542bed16c4..8e0224669f2 100644 --- a/src/IO/WriteBufferAIO.cpp +++ b/src/IO/WriteBufferAIO.cpp @@ -1,4 +1,4 @@ -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include #include diff --git a/src/IO/WriteBufferAIO.h b/src/IO/WriteBufferAIO.h index 4fdeac9e9b9..f514acab359 100644 --- a/src/IO/WriteBufferAIO.h +++ b/src/IO/WriteBufferAIO.h @@ -1,6 +1,6 @@ #pragma once -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include #include diff --git a/src/IO/createReadBufferFromFileBase.cpp b/src/IO/createReadBufferFromFileBase.cpp index 9fa560620dd..c1d4377fdff 100644 --- a/src/IO/createReadBufferFromFileBase.cpp +++ b/src/IO/createReadBufferFromFileBase.cpp @@ -1,6 +1,6 @@ #include #include -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include #endif #include @@ -24,7 +24,7 @@ std::unique_ptr createReadBufferFromFileBase( size_t estimated_size, size_t aio_threshold, size_t mmap_threshold, size_t buffer_size_, int flags_, char * existing_memory_, size_t alignment) { -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) if (aio_threshold && estimated_size >= aio_threshold) { /// Attempt to open a file with O_DIRECT diff --git a/src/IO/createWriteBufferFromFileBase.cpp b/src/IO/createWriteBufferFromFileBase.cpp index d20af3ede76..6022457f32e 100644 --- a/src/IO/createWriteBufferFromFileBase.cpp +++ b/src/IO/createWriteBufferFromFileBase.cpp @@ -1,6 +1,6 @@ #include #include -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) #include #endif #include @@ -20,7 +20,7 @@ std::unique_ptr createWriteBufferFromFileBase(const std size_t aio_threshold, size_t buffer_size_, int flags_, mode_t mode, char * existing_memory_, size_t alignment) { -#if defined(__linux__) || defined(__FreeBSD__) +#if defined(OS_LINUX) || defined(__FreeBSD__) if (aio_threshold && estimated_size >= aio_threshold) { /// Attempt to open a file with O_DIRECT From 560151f6cde45b6bda2f8fe92e62b34cd3bc274c Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Wed, 15 Jul 2020 13:24:33 +0200 Subject: [PATCH 092/143] * Fix bug in StorageLiveView.cpp * Fixing synchronization of the first insert in live view tests --- src/Storages/LiveView/StorageLiveView.cpp | 10 ++++++++-- .../00962_temporary_live_view_watch_live.py | 1 + ..._temporary_live_view_watch_live_timeout.py.disabled | 1 + .../0_stateless/00965_live_view_watch_heartbeat.py | 1 + .../00979_live_view_watch_continuous_aggregates.py | 4 ++-- .../queries/0_stateless/00979_live_view_watch_live.py | 1 + .../00979_live_view_watch_live_moving_avg.py | 1 + .../00979_live_view_watch_live_with_subquery.py | 1 + .../0_stateless/01246_insert_into_watch_live_view.py | 4 ++-- 9 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/Storages/LiveView/StorageLiveView.cpp b/src/Storages/LiveView/StorageLiveView.cpp index efd0a71b18f..3d2e9657439 100644 --- a/src/Storages/LiveView/StorageLiveView.cpp +++ b/src/Storages/LiveView/StorageLiveView.cpp @@ -328,8 +328,14 @@ bool StorageLiveView::getNewBlocks() BlocksPtr new_blocks = std::make_shared(); BlocksMetadataPtr new_blocks_metadata = std::make_shared(); - mergeable_blocks = collectMergeableBlocks(*live_view_context); - Pipes from = blocksToPipes(mergeable_blocks->blocks, mergeable_blocks->sample_block); + /// can't set mergeable_blocks here or anywhere else outside the writeIntoLiveView function + /// as there could be a race codition when the new block has been inserted into + /// the source table by the PushingToViewsBlockOutputStream and this method + /// called before writeIntoLiveView function is called which can lead to + /// the same block added twice to the mergeable_blocks leading to + /// inserted data to be duplicated + auto _mergeable_blocks = collectMergeableBlocks(*live_view_context); + Pipes from = blocksToPipes(_mergeable_blocks->blocks, _mergeable_blocks->sample_block); BlockInputStreamPtr data = completeQuery(std::move(from)); while (Block block = data->read()) diff --git a/tests/queries/0_stateless/00962_temporary_live_view_watch_live.py b/tests/queries/0_stateless/00962_temporary_live_view_watch_live.py index fb603a43f9e..c6a5251fbee 100755 --- a/tests/queries/0_stateless/00962_temporary_live_view_watch_live.py +++ b/tests/queries/0_stateless/00962_temporary_live_view_watch_live.py @@ -30,6 +30,7 @@ with client(name='client1>', log=log) as client1, client(name='client2>', log=lo client1.send('CREATE LIVE VIEW test.lv WITH TIMEOUT AS SELECT sum(a) FROM test.mt') client1.expect(prompt) client1.send('WATCH test.lv') + client1.expect('_version') client1.expect(r'0.*1' + end_of_block) client2.send('INSERT INTO test.mt VALUES (1),(2),(3)') client1.expect(r'6.*2' + end_of_block) diff --git a/tests/queries/0_stateless/00963_temporary_live_view_watch_live_timeout.py.disabled b/tests/queries/0_stateless/00963_temporary_live_view_watch_live_timeout.py.disabled index 69722d9161c..525e7022156 100755 --- a/tests/queries/0_stateless/00963_temporary_live_view_watch_live_timeout.py.disabled +++ b/tests/queries/0_stateless/00963_temporary_live_view_watch_live_timeout.py.disabled @@ -30,6 +30,7 @@ with client(name='client1>', log=log) as client1, client(name='client2>', log=lo client1.send('CREATE LIVE VIEW test.lv WITH TIMEOUT 1 AS SELECT sum(a) FROM test.mt') client1.expect(prompt) client1.send('WATCH test.lv') + client1.expect('_version') client1.expect(r'0.*1' + end_of_block) client2.send('INSERT INTO test.mt VALUES (1),(2),(3)') client2.expect(prompt) diff --git a/tests/queries/0_stateless/00965_live_view_watch_heartbeat.py b/tests/queries/0_stateless/00965_live_view_watch_heartbeat.py index 08d94a2341d..a20c9c3919c 100755 --- a/tests/queries/0_stateless/00965_live_view_watch_heartbeat.py +++ b/tests/queries/0_stateless/00965_live_view_watch_heartbeat.py @@ -32,6 +32,7 @@ with client(name='client1>', log=log) as client1, client(name='client2>', log=lo client1.send('CREATE LIVE VIEW test.lv WITH TIMEOUT AS SELECT sum(a) FROM test.mt') client1.expect(prompt) client1.send('WATCH test.lv') + client1.expect('_version') client1.expect(r'0.*1' + end_of_block) client2.send('INSERT INTO test.mt VALUES (1),(2),(3)') client1.expect(r'6.*2' + end_of_block) diff --git a/tests/queries/0_stateless/00979_live_view_watch_continuous_aggregates.py b/tests/queries/0_stateless/00979_live_view_watch_continuous_aggregates.py index d184fea7183..3a67226da80 100755 --- a/tests/queries/0_stateless/00979_live_view_watch_continuous_aggregates.py +++ b/tests/queries/0_stateless/00979_live_view_watch_continuous_aggregates.py @@ -29,8 +29,8 @@ with client(name='client1>', log=log) as client1, client(name='client2>', log=lo client1.expect(prompt) client1.send('CREATE LIVE VIEW test.lv AS SELECT toStartOfDay(time) AS day, location, avg(temperature) FROM test.mt GROUP BY day, location ORDER BY day, location') client1.expect(prompt) - client1.send('WATCH test.lv FORMAT CSV') - client1.expect(r'0.*1' + end_of_block) + client1.send('WATCH test.lv FORMAT CSVWithNames') + client1.expect(r'_version') client2.send("INSERT INTO test.mt VALUES ('2019-01-01 00:00:00','New York',60),('2019-01-01 00:10:00','New York',70)") client2.expect(prompt) client1.expect(r'"2019-01-01 00:00:00","New York",65') diff --git a/tests/queries/0_stateless/00979_live_view_watch_live.py b/tests/queries/0_stateless/00979_live_view_watch_live.py index 784afa14498..04ca070c969 100755 --- a/tests/queries/0_stateless/00979_live_view_watch_live.py +++ b/tests/queries/0_stateless/00979_live_view_watch_live.py @@ -30,6 +30,7 @@ with client(name='client1>', log=log) as client1, client(name='client2>', log=lo client1.send('CREATE LIVE VIEW test.lv AS SELECT sum(a) FROM test.mt') client1.expect(prompt) client1.send('WATCH test.lv') + client1.expect('_version') client1.expect(r'0.*1' + end_of_block) client2.send('INSERT INTO test.mt VALUES (1),(2),(3)') client1.expect(r'6.*2' + end_of_block) diff --git a/tests/queries/0_stateless/00979_live_view_watch_live_moving_avg.py b/tests/queries/0_stateless/00979_live_view_watch_live_moving_avg.py index 30d5e6d67b3..ccc824c4d20 100755 --- a/tests/queries/0_stateless/00979_live_view_watch_live_moving_avg.py +++ b/tests/queries/0_stateless/00979_live_view_watch_live_moving_avg.py @@ -30,6 +30,7 @@ with client(name='client1>', log=log) as client1, client(name='client2>', log=lo client1.send('CREATE LIVE VIEW test.lv AS SELECT sum(a)/2 FROM (SELECT a, id FROM ( SELECT a, id FROM test.mt ORDER BY id DESC LIMIT 2 ) ORDER BY id DESC LIMIT 2)') client1.expect(prompt) client1.send('WATCH test.lv') + client1.expect('_version') client1.expect(r'0.*1' + end_of_block) client2.send('INSERT INTO test.mt VALUES (1, 1),(2, 2),(3, 3)') client1.expect(r'2\.5.*2' + end_of_block) diff --git a/tests/queries/0_stateless/00979_live_view_watch_live_with_subquery.py b/tests/queries/0_stateless/00979_live_view_watch_live_with_subquery.py index 44c923d75d8..809b8b0342a 100755 --- a/tests/queries/0_stateless/00979_live_view_watch_live_with_subquery.py +++ b/tests/queries/0_stateless/00979_live_view_watch_live_with_subquery.py @@ -30,6 +30,7 @@ with client(name='client1>', log=log) as client1, client(name='client2>', log=lo client1.send('CREATE LIVE VIEW test.lv AS SELECT * FROM ( SELECT sum(A.a) FROM (SELECT * FROM test.mt) AS A )') client1.expect(prompt) client1.send('WATCH test.lv') + client1.expect('_version') client1.expect(r'0.*1' + end_of_block) client2.send('INSERT INTO test.mt VALUES (1),(2),(3)') client1.expect(r'6.*2' + end_of_block) diff --git a/tests/queries/0_stateless/01246_insert_into_watch_live_view.py b/tests/queries/0_stateless/01246_insert_into_watch_live_view.py index ee417c68897..7f65a7135d5 100755 --- a/tests/queries/0_stateless/01246_insert_into_watch_live_view.py +++ b/tests/queries/0_stateless/01246_insert_into_watch_live_view.py @@ -38,8 +38,8 @@ with client(name='client1>', log=log) as client1, client(name='client2>', log=lo client3.send('CREATE LIVE VIEW test.lv_sums AS SELECT * FROM test.sums ORDER BY version') client3.expect(prompt) - client3.send("WATCH test.lv_sums FORMAT CSV") - client3.expect(r'0.*1' + end_of_block) + client3.send("WATCH test.lv_sums FORMAT CSVWithNames") + client3.expect('_version') client1.send('INSERT INTO test.sums WATCH test.lv') client1.expect(r'INSERT INTO') From ba05bb1b398f9b407e148182850a35621d8d8a29 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 14:47:51 +0300 Subject: [PATCH 093/143] Better tests for parallel run --- docker/test/fasttest/run.sh | 2 +- .../0_stateless/00626_replace_partition_from_table.sql | 2 +- .../00653_verification_monotonic_data_load.sh | 10 +++++++--- .../00738_nested_merge_multidimensional_array.sql | 4 ++-- .../0_stateless/00988_parallel_parts_removal.sql | 4 ++-- .../0_stateless/00989_parallel_parts_loading.sql | 4 ++-- ..._incremental_streaming_from_2_src_with_feedback.sql | 6 +++--- .../0_stateless/01213_alter_rename_column_zookeeper.sh | 4 ++-- .../0_stateless/01282_system_parts_ttl_info.sql | 4 ++-- .../01373_summing_merge_tree_exclude_partition_key.sql | 4 ++-- 10 files changed, 24 insertions(+), 20 deletions(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index eb4b6ad3ff0..fa82c071aaf 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -90,7 +90,7 @@ do sleep 0.1 done -TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter" +TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent" clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt diff --git a/tests/queries/0_stateless/00626_replace_partition_from_table.sql b/tests/queries/0_stateless/00626_replace_partition_from_table.sql index c6479a94060..7224224334e 100644 --- a/tests/queries/0_stateless/00626_replace_partition_from_table.sql +++ b/tests/queries/0_stateless/00626_replace_partition_from_table.sql @@ -62,7 +62,7 @@ SELECT count(), sum(d) FROM dst; SELECT 'OPTIMIZE'; SELECT count(), sum(d), uniqExact(_part) FROM dst; -SYSTEM START MERGES; +SYSTEM START MERGES dst; SET optimize_throw_if_noop=1; OPTIMIZE TABLE dst; SELECT count(), sum(d), uniqExact(_part) FROM dst; diff --git a/tests/queries/0_stateless/00653_verification_monotonic_data_load.sh b/tests/queries/0_stateless/00653_verification_monotonic_data_load.sh index e52610f03ba..bb248b5f4e1 100755 --- a/tests/queries/0_stateless/00653_verification_monotonic_data_load.sh +++ b/tests/queries/0_stateless/00653_verification_monotonic_data_load.sh @@ -25,9 +25,15 @@ ${CLICKHOUSE_CLIENT} --query="CREATE TABLE fixed_string_test_table (val FixedStr ${CLICKHOUSE_CLIENT} --query="CREATE TABLE signed_integer_test_table (val Int32) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" ${CLICKHOUSE_CLIENT} --query="CREATE TABLE unsigned_integer_test_table (val UInt32) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" ${CLICKHOUSE_CLIENT} --query="CREATE TABLE enum_test_table (val Enum16('hello' = 1, 'world' = 2, 'yandex' = 256, 'clickhouse' = 257)) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" + ${CLICKHOUSE_CLIENT} --query="CREATE TABLE date_test_table (val Date) ENGINE = MergeTree ORDER BY val SETTINGS index_granularity = 1, index_granularity_bytes = 0;" -${CLICKHOUSE_CLIENT} --query="SYSTEM STOP MERGES;" +${CLICKHOUSE_CLIENT} --query="SYSTEM STOP MERGES string_test_table;" +${CLICKHOUSE_CLIENT} --query="SYSTEM STOP MERGES fixed_string_test_table;" +${CLICKHOUSE_CLIENT} --query="SYSTEM STOP MERGES signed_integer_test_table;" +${CLICKHOUSE_CLIENT} --query="SYSTEM STOP MERGES unsigned_integer_test_table;" +${CLICKHOUSE_CLIENT} --query="SYSTEM STOP MERGES enum_test_table;" +${CLICKHOUSE_CLIENT} --query="SYSTEM STOP MERGES date_test_table;" ${CLICKHOUSE_CLIENT} --query="INSERT INTO string_test_table VALUES ('0'), ('2'), ('2');" ${CLICKHOUSE_CLIENT} --query="INSERT INTO fixed_string_test_table VALUES ('0'), ('2'), ('2');" @@ -80,5 +86,3 @@ ${CLICKHOUSE_CLIENT} --query="DROP TABLE IF EXISTS signed_integer_test_table;" ${CLICKHOUSE_CLIENT} --query="DROP TABLE IF EXISTS unsigned_integer_test_table;" ${CLICKHOUSE_CLIENT} --query="DROP TABLE IF EXISTS enum_test_table;" ${CLICKHOUSE_CLIENT} --query="DROP TABLE IF EXISTS date_test_table;" - -${CLICKHOUSE_CLIENT} --query="SYSTEM START MERGES;" diff --git a/tests/queries/0_stateless/00738_nested_merge_multidimensional_array.sql b/tests/queries/0_stateless/00738_nested_merge_multidimensional_array.sql index f9ccd9623e1..6efeb2e6ef5 100644 --- a/tests/queries/0_stateless/00738_nested_merge_multidimensional_array.sql +++ b/tests/queries/0_stateless/00738_nested_merge_multidimensional_array.sql @@ -1,13 +1,13 @@ DROP TABLE IF EXISTS sites; CREATE TABLE sites (Domain UInt8, `Users.UserID` Array(UInt64), `Users.Dates` Array(Array(Date))) ENGINE = MergeTree ORDER BY Domain SETTINGS vertical_merge_algorithm_min_rows_to_activate = 0, vertical_merge_algorithm_min_columns_to_activate = 0; -SYSTEM STOP MERGES; +SYSTEM STOP MERGES sites; INSERT INTO sites VALUES (1,[1],[[]]); INSERT INTO sites VALUES (2,[1],[['2018-06-22']]); SELECT count(), countArray(Users.Dates), countArrayArray(Users.Dates) FROM sites; -SYSTEM START MERGES; +SYSTEM START MERGES sites; OPTIMIZE TABLE sites FINAL; SELECT count(), countArray(Users.Dates), countArrayArray(Users.Dates) FROM sites; diff --git a/tests/queries/0_stateless/00988_parallel_parts_removal.sql b/tests/queries/0_stateless/00988_parallel_parts_removal.sql index 0dccd3df048..bff9bbe6d8d 100644 --- a/tests/queries/0_stateless/00988_parallel_parts_removal.sql +++ b/tests/queries/0_stateless/00988_parallel_parts_removal.sql @@ -2,7 +2,7 @@ DROP TABLE IF EXISTS mt; CREATE TABLE mt (x UInt64) ENGINE = MergeTree ORDER BY x SETTINGS max_part_removal_threads = 16, cleanup_delay_period = 1, cleanup_delay_period_random_add = 0, old_parts_lifetime = 1, parts_to_delay_insert = 100000, parts_to_throw_insert = 100000; -SYSTEM STOP MERGES; +SYSTEM STOP MERGES mt; SET max_block_size = 1, min_insert_block_size_rows = 0, min_insert_block_size_bytes = 0; INSERT INTO mt SELECT * FROM numbers(1000); @@ -10,7 +10,7 @@ SET max_block_size = 65536; SELECT count(), sum(x) FROM mt; -SYSTEM START MERGES; +SYSTEM START MERGES mt; OPTIMIZE TABLE mt FINAL; SELECT count(), sum(x) FROM mt; diff --git a/tests/queries/0_stateless/00989_parallel_parts_loading.sql b/tests/queries/0_stateless/00989_parallel_parts_loading.sql index 5e0011483b3..0b4c0501669 100644 --- a/tests/queries/0_stateless/00989_parallel_parts_loading.sql +++ b/tests/queries/0_stateless/00989_parallel_parts_loading.sql @@ -2,7 +2,7 @@ DROP TABLE IF EXISTS mt; CREATE TABLE mt (x UInt64) ENGINE = MergeTree ORDER BY x SETTINGS max_part_loading_threads = 16, parts_to_delay_insert = 100000, parts_to_throw_insert = 100000; -SYSTEM STOP MERGES; +SYSTEM STOP MERGES mt; SET max_block_size = 1, min_insert_block_size_rows = 0, min_insert_block_size_bytes = 0; INSERT INTO mt SELECT * FROM numbers(1000); @@ -15,5 +15,5 @@ ATTACH TABLE mt; SELECT count(), sum(x) FROM mt; -SYSTEM START MERGES; +SYSTEM START MERGES mt; DROP TABLE mt; diff --git a/tests/queries/0_stateless/01064_incremental_streaming_from_2_src_with_feedback.sql b/tests/queries/0_stateless/01064_incremental_streaming_from_2_src_with_feedback.sql index c2d0333bf46..cdefdd9de8a 100644 --- a/tests/queries/0_stateless/01064_incremental_streaming_from_2_src_with_feedback.sql +++ b/tests/queries/0_stateless/01064_incremental_streaming_from_2_src_with_feedback.sql @@ -76,7 +76,9 @@ AS GROUP BY id; -- This query has effect only for existing tables, so it must be located after CREATE. -SYSTEM STOP MERGES; +SYSTEM STOP MERGES target_table; +SYSTEM STOP MERGES checkouts; +SYSTEM STOP MERGES logins; -- feed with some initial values INSERT INTO logins SELECT number as id, '2000-01-01 08:00:00' from numbers(50000); @@ -126,5 +128,3 @@ DROP TABLE IF EXISTS mv_logins2target; DROP TABLE IF EXISTS checkouts; DROP TABLE IF EXISTS mv_checkouts2target; DROP TABLE target_table; - -SYSTEM START MERGES; diff --git a/tests/queries/0_stateless/01213_alter_rename_column_zookeeper.sh b/tests/queries/0_stateless/01213_alter_rename_column_zookeeper.sh index d7b8ea3262d..009b400ee7b 100755 --- a/tests/queries/0_stateless/01213_alter_rename_column_zookeeper.sh +++ b/tests/queries/0_stateless/01213_alter_rename_column_zookeeper.sh @@ -24,7 +24,7 @@ $CLICKHOUSE_CLIENT --query "INSERT INTO table_for_rename_replicated SELECT toDat $CLICKHOUSE_CLIENT --query "SELECT value1 FROM table_for_rename_replicated WHERE key = 1;" -$CLICKHOUSE_CLIENT --query "SYSTEM STOP MERGES;" +$CLICKHOUSE_CLIENT --query "SYSTEM STOP MERGES table_for_rename_replicated;" $CLICKHOUSE_CLIENT --query "SHOW CREATE TABLE table_for_rename_replicated;" @@ -49,7 +49,7 @@ $CLICKHOUSE_CLIENT --query "SELECT renamed_value1 FROM table_for_rename_replicat $CLICKHOUSE_CLIENT --query "SELECT * FROM table_for_rename_replicated WHERE key = 1 FORMAT TSVWithNames;" -$CLICKHOUSE_CLIENT --query "SYSTEM START MERGES;" +$CLICKHOUSE_CLIENT --query "SYSTEM START MERGES table_for_rename_replicated;" $CLICKHOUSE_CLIENT --query "SYSTEM SYNC REPLICA table_for_rename_replicated;" diff --git a/tests/queries/0_stateless/01282_system_parts_ttl_info.sql b/tests/queries/0_stateless/01282_system_parts_ttl_info.sql index 3a1b1cc79ce..0caf64bac8d 100644 --- a/tests/queries/0_stateless/01282_system_parts_ttl_info.sql +++ b/tests/queries/0_stateless/01282_system_parts_ttl_info.sql @@ -1,9 +1,9 @@ DROP TABLE IF EXISTS ttl; CREATE TABLE ttl (d DateTime) ENGINE = MergeTree ORDER BY tuple() TTL d + INTERVAL 10 DAY; -SYSTEM STOP MERGES; +SYSTEM STOP MERGES ttl; INSERT INTO ttl VALUES ('2000-01-01 01:02:03'), ('2000-02-03 04:05:06'); SELECT rows, delete_ttl_info_min, delete_ttl_info_max, move_ttl_info.expression, move_ttl_info.min, move_ttl_info.max FROM system.parts WHERE database = currentDatabase() AND table = 'ttl'; -SYSTEM START MERGES; +SYSTEM START MERGES ttl; OPTIMIZE TABLE ttl FINAL; SELECT rows, delete_ttl_info_min, delete_ttl_info_max, move_ttl_info.expression, move_ttl_info.min, move_ttl_info.max FROM system.parts WHERE database = currentDatabase() AND table = 'ttl' AND active; DROP TABLE ttl; diff --git a/tests/queries/0_stateless/01373_summing_merge_tree_exclude_partition_key.sql b/tests/queries/0_stateless/01373_summing_merge_tree_exclude_partition_key.sql index 60c988a2e2f..790fbca6b73 100644 --- a/tests/queries/0_stateless/01373_summing_merge_tree_exclude_partition_key.sql +++ b/tests/queries/0_stateless/01373_summing_merge_tree_exclude_partition_key.sql @@ -4,7 +4,7 @@ CREATE TABLE tt_01373 (a Int64, d Int64, val Int64) ENGINE = SummingMergeTree PARTITION BY (a) ORDER BY (d); -SYSTEM STOP MERGES; +SYSTEM STOP MERGES tt_01373; INSERT INTO tt_01373 SELECT number%13, number%17, 1 from numbers(1000000); @@ -17,7 +17,7 @@ SELECT count(*) FROM tt_01373 FINAL; SELECT '---'; SELECT a, count() FROM tt_01373 FINAL GROUP BY a ORDER BY a; -SYSTEM START MERGES; +SYSTEM START MERGES tt_01373; OPTIMIZE TABLE tt_01373 FINAL; SELECT '---'; From 3ab7bdbbbb3ef3308a16c3c4477d243e5557abaa Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 15:16:59 +0300 Subject: [PATCH 094/143] One more test to skip --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index fa82c071aaf..d65d21cdef8 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -90,7 +90,7 @@ do sleep 0.1 done -TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent" +TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading" clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt From 2dcb08c000feca0a72b7c4bb1279c79fae8a7936 Mon Sep 17 00:00:00 2001 From: Ivan Blinkov Date: Wed, 15 Jul 2020 15:55:09 +0300 Subject: [PATCH 095/143] Update docs.css --- website/css/docs.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/css/docs.css b/website/css/docs.css index 14c72f1894b..ecd03a02422 100644 --- a/website/css/docs.css +++ b/website/css/docs.css @@ -1,5 +1,6 @@ details { background: #444451; + color: #eee; padding: 1rem; margin-bottom: 1rem; margin-top: 1rem; @@ -7,7 +8,7 @@ details { summary { font-weight: bold; - color: #fff; + color: #eee; } #sidebar { From 78f69bbfc41f33ad9bc56de1f2cbfd7e95a15551 Mon Sep 17 00:00:00 2001 From: Vasily Nemkov Date: Wed, 15 Jul 2020 16:11:43 +0300 Subject: [PATCH 096/143] Retain existing config.d/query_masking_rules.xml that come from server package --- docker/test/stateful_with_coverage/run.sh | 27 +++++++------ docker/test/stateless/run.sh | 5 ++- docker/test/stateless_with_coverage/run.sh | 45 ++++++++++++---------- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/docker/test/stateful_with_coverage/run.sh b/docker/test/stateful_with_coverage/run.sh index 66877362d10..8928fc28f80 100755 --- a/docker/test/stateful_with_coverage/run.sh +++ b/docker/test/stateful_with_coverage/run.sh @@ -55,18 +55,21 @@ ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-serv ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/dict_examples/; \ ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/dict_examples/; -ln -s /usr/share/clickhouse-test/config/zookeeper.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/listen.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/text_log.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/metric_log.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/query_masking_rules.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/; \ - ln -s /usr/share/clickhouse-test/config/readonly.xml /etc/clickhouse-server/users.d/; \ - ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-server/; \ - ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/; \ - ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/; \ - ln -s /usr/share/clickhouse-test/config/macros.xml /etc/clickhouse-server/config.d/; +ln -s /usr/share/clickhouse-test/config/zookeeper.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/listen.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/text_log.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/metric_log.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/ +ln -s /usr/share/clickhouse-test/config/readonly.xml /etc/clickhouse-server/users.d/ +ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/macros.xml /etc/clickhouse-server/config.d/ + +# Retain any pre-existing config and allow ClickHouse to load those if required +ln -s --backup=simple --suffix=_original.xml \ + /usr/share/clickhouse-test/config/query_masking_rules.xml /etc/clickhouse-server/config.d/ service zookeeper start diff --git a/docker/test/stateless/run.sh b/docker/test/stateless/run.sh index 08adc94f535..a221e76f2f0 100755 --- a/docker/test/stateless/run.sh +++ b/docker/test/stateless/run.sh @@ -17,7 +17,6 @@ ln -s /usr/share/clickhouse-test/config/listen.xml /etc/clickhouse-server/config ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/ ln -s /usr/share/clickhouse-test/config/text_log.xml /etc/clickhouse-server/config.d/ ln -s /usr/share/clickhouse-test/config/metric_log.xml /etc/clickhouse-server/config.d/ -ln -s /usr/share/clickhouse-test/config/query_masking_rules.xml /etc/clickhouse-server/config.d/ ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/ ln -s /usr/share/clickhouse-test/config/readonly.xml /etc/clickhouse-server/users.d/ ln -s /usr/share/clickhouse-test/config/access_management.xml /etc/clickhouse-server/users.d/ @@ -33,6 +32,10 @@ ln -s /usr/share/clickhouse-test/config/server.key /etc/clickhouse-server/ ln -s /usr/share/clickhouse-test/config/server.crt /etc/clickhouse-server/ ln -s /usr/share/clickhouse-test/config/dhparam.pem /etc/clickhouse-server/ +# Retain any pre-existing config and allow ClickHouse to load it if required +ln -s --backup=simple --suffix=_original.xml \ + /usr/share/clickhouse-test/config/query_masking_rules.xml /etc/clickhouse-server/config.d/ + if [[ -n "$USE_POLYMORPHIC_PARTS" ]] && [[ "$USE_POLYMORPHIC_PARTS" -eq 1 ]]; then ln -s /usr/share/clickhouse-test/config/polymorphic_parts.xml /etc/clickhouse-server/config.d/ fi diff --git a/docker/test/stateless_with_coverage/run.sh b/docker/test/stateless_with_coverage/run.sh index 64e171b2869..64317ee62fd 100755 --- a/docker/test/stateless_with_coverage/run.sh +++ b/docker/test/stateless_with_coverage/run.sh @@ -46,27 +46,30 @@ ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-serv ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/dict_examples/; \ ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/dict_examples/; -ln -s /usr/share/clickhouse-test/config/zookeeper.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/listen.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/text_log.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/metric_log.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/query_masking_rules.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/; \ - ln -s /usr/share/clickhouse-test/config/readonly.xml /etc/clickhouse-server/users.d/; \ - ln -s /usr/share/clickhouse-test/config/access_management.xml /etc/clickhouse-server/users.d/; \ - ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-server/; \ - ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/; \ - ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/; \ - ln -s /usr/share/clickhouse-test/config/macros.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/disks.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/secure_ports.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/clusters.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/graphite.xml /etc/clickhouse-server/config.d/; \ - ln -s /usr/share/clickhouse-test/config/server.key /etc/clickhouse-server/; \ - ln -s /usr/share/clickhouse-test/config/server.crt /etc/clickhouse-server/; \ - ln -s /usr/share/clickhouse-test/config/dhparam.pem /etc/clickhouse-server/; \ - ln -sf /usr/share/clickhouse-test/config/client_config.xml /etc/clickhouse-client/config.xml +ln -s /usr/share/clickhouse-test/config/zookeeper.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/listen.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/part_log.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/text_log.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/metric_log.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/log_queries.xml /etc/clickhouse-server/users.d/ +ln -s /usr/share/clickhouse-test/config/readonly.xml /etc/clickhouse-server/users.d/ +ln -s /usr/share/clickhouse-test/config/access_management.xml /etc/clickhouse-server/users.d/ +ln -s /usr/share/clickhouse-test/config/ints_dictionary.xml /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/strings_dictionary.xml /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/decimals_dictionary.xml /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/macros.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/disks.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/secure_ports.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/clusters.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/graphite.xml /etc/clickhouse-server/config.d/ +ln -s /usr/share/clickhouse-test/config/server.key /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/server.crt /etc/clickhouse-server/ +ln -s /usr/share/clickhouse-test/config/dhparam.pem /etc/clickhouse-server/ +ln -sf /usr/share/clickhouse-test/config/client_config.xml /etc/clickhouse-client/config.xml + +# Retain any pre-existing config and allow ClickHouse to load it if required +ln -s --backup=simple --suffix=_original.xml \ + /usr/share/clickhouse-test/config/query_masking_rules.xml /etc/clickhouse-server/config.d/ service zookeeper start sleep 5 From fcee86efc6ea074992cb50aa81a642ab63b4d4cf Mon Sep 17 00:00:00 2001 From: Konstantin Lebedev Date: Wed, 15 Jul 2020 16:30:05 +0300 Subject: [PATCH 097/143] Update adopters.md --- docs/en/introduction/adopters.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/en/introduction/adopters.md b/docs/en/introduction/adopters.md index 7487b212955..c4f119ebab7 100644 --- a/docs/en/introduction/adopters.md +++ b/docs/en/introduction/adopters.md @@ -44,6 +44,7 @@ toc_title: Adopters | Lawrence Berkeley National Laboratory | Research | Traffic analysis | 1 server | 11.8 TiB | [Slides in English, April 2019](https://www.smitasin.com/presentations/2019-04-17_DOE-NSM.pdf) | | LifeStreet | Ad network | Main product | 75 servers (3 replicas) | 5.27 PiB | [Blog post in Russian, February 2017](https://habr.com/en/post/322620/) | | Mail.ru Cloud Solutions | Cloud services | Main product | — | — | [Article in Russian](https://mcs.mail.ru/help/db-create/clickhouse#) | +| Marilyn | Advertising | Statistics | — | — | [Talk in Russian, June 2017](https://www.youtube.com/watch?v=iXlIgx2khwc) | | MessageBird | Telecommunications | Statistics | — | — | [Slides in English, November 2018](https://github.com/ClickHouse/clickhouse-presentations/blob/master/meetup20/messagebird.pdf) | | MGID | Ad network | Web-analytics | — | — | [Blog post in Russian, April 2020](http://gs-studio.com/news-about-it/32777----clickhouse---c) | | OneAPM | Monitorings and Data Analysis | Main product | — | — | [Slides in Chinese, October 2018](https://github.com/ClickHouse/clickhouse-presentations/blob/master/meetup19/8.%20clickhouse在OneAPM的应用%20杜龙.pdf) | From 00acf4173cc665eea0ba0a0e4257bb22db52e5c0 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Wed, 15 Jul 2020 16:29:00 +0300 Subject: [PATCH 098/143] Fixes for perf test after #12469 --- docker/test/performance-comparison/compare.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docker/test/performance-comparison/compare.sh b/docker/test/performance-comparison/compare.sh index 8e6221b5195..378e87f443b 100755 --- a/docker/test/performance-comparison/compare.sh +++ b/docker/test/performance-comparison/compare.sh @@ -498,7 +498,8 @@ create table queries engine File(TSVWithNamesAndTypes, 'report/queries.tsv') left, right, diff, stat_threshold, if(report_threshold > 0, report_threshold, 0.10) as report_threshold, - test, query_index, query_display_name + query_metric_stats.test test, query_metric_stats.query_index query_index, + query_display_name from query_metric_stats left join file('analyze/report-thresholds.tsv', TSV, 'test text, report_threshold float') thresholds @@ -666,7 +667,8 @@ create view query_display_names as select * from create table unstable_query_runs engine File(TSVWithNamesAndTypes, 'unstable-query-runs.$version.rep') as - select test, query_index, query_display_name, query_id + select query_runs.test test, query_runs.query_index query_index, + query_display_name, query_id from query_runs join queries_for_flamegraph on query_runs.test = queries_for_flamegraph.test From 9232caed0713d6eea8d6cbea3677a526abb3ccf1 Mon Sep 17 00:00:00 2001 From: Artem Zuikov Date: Wed, 15 Jul 2020 16:55:51 +0300 Subject: [PATCH 099/143] Update arcadia_skip_list.txt one more ignored test with dictionary --- tests/queries/0_stateless/arcadia_skip_list.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/queries/0_stateless/arcadia_skip_list.txt b/tests/queries/0_stateless/arcadia_skip_list.txt index 55c011e4884..b5c2b21d683 100644 --- a/tests/queries/0_stateless/arcadia_skip_list.txt +++ b/tests/queries/0_stateless/arcadia_skip_list.txt @@ -131,3 +131,4 @@ 01370_client_autocomplete_word_break_characters 01319_optimize_skip_unused_shards_nesting 01376_GROUP_BY_injective_elimination_dictGet +01391_join_on_dict_crash.sql From 2ba23c0cfaf888b9b162f3579b10cb4d4873f29a Mon Sep 17 00:00:00 2001 From: Artem Zuikov Date: Wed, 15 Jul 2020 16:56:13 +0300 Subject: [PATCH 100/143] Update arcadia_skip_list.txt hotfix --- tests/queries/0_stateless/arcadia_skip_list.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/queries/0_stateless/arcadia_skip_list.txt b/tests/queries/0_stateless/arcadia_skip_list.txt index b5c2b21d683..bc0dd67519a 100644 --- a/tests/queries/0_stateless/arcadia_skip_list.txt +++ b/tests/queries/0_stateless/arcadia_skip_list.txt @@ -131,4 +131,4 @@ 01370_client_autocomplete_word_break_characters 01319_optimize_skip_unused_shards_nesting 01376_GROUP_BY_injective_elimination_dictGet -01391_join_on_dict_crash.sql +01391_join_on_dict_crash From ed4da4bec6e3268d0354eb26bfbeb8c8b32e110e Mon Sep 17 00:00:00 2001 From: Vladimir Chebotarev Date: Wed, 15 Jul 2020 17:16:45 +0300 Subject: [PATCH 101/143] Separated `AWSAuthV4Signer` into different logger, removed "AWSClient: AWSClient" (#12320) --- src/IO/S3Common.cpp | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/IO/S3Common.cpp b/src/IO/S3Common.cpp index 20ff38150eb..f5296b65a0d 100644 --- a/src/IO/S3Common.cpp +++ b/src/IO/S3Common.cpp @@ -22,6 +22,12 @@ namespace { + +const char * S3_LOGGER_TAG_NAMES[][2] = { + {"AWSClient", "AWSClient"}, + {"AWSAuthV4Signer", "AWSClient (AWSAuthV4Signer)"}, +}; + const std::pair & convertLogLevel(Aws::Utils::Logging::LogLevel log_level) { static const std::unordered_map> mapping = @@ -40,26 +46,46 @@ const std::pair & convertLogLevel(Aws::U class AWSLogger final : public Aws::Utils::Logging::LogSystemInterface { public: + AWSLogger() + { + for (auto [tag, name] : S3_LOGGER_TAG_NAMES) + tag_loggers[tag] = &Poco::Logger::get(name); + + default_logger = tag_loggers[S3_LOGGER_TAG_NAMES[0][0]]; + } + ~AWSLogger() final = default; Aws::Utils::Logging::LogLevel GetLogLevel() const final { return Aws::Utils::Logging::LogLevel::Trace; } void Log(Aws::Utils::Logging::LogLevel log_level, const char * tag, const char * format_str, ...) final // NOLINT { - const auto & [level, prio] = convertLogLevel(log_level); - LOG_IMPL(log, level, prio, "{}: {}", tag, format_str); + callLogImpl(log_level, tag, format_str); /// FIXME. Variadic arguments? } void LogStream(Aws::Utils::Logging::LogLevel log_level, const char * tag, const Aws::OStringStream & message_stream) final + { + callLogImpl(log_level, tag, message_stream.str().c_str()); + } + + void callLogImpl(Aws::Utils::Logging::LogLevel log_level, const char * tag, const char * message) { const auto & [level, prio] = convertLogLevel(log_level); - LOG_IMPL(log, level, prio, "{}: {}", tag, message_stream.str()); + if (tag_loggers.count(tag) > 0) + { + LOG_IMPL(tag_loggers[tag], level, prio, "{}", message); + } + else + { + LOG_IMPL(default_logger, level, prio, "{}: {}", tag, message); + } } void Flush() final {} private: - Poco::Logger * log = &Poco::Logger::get("AWSClient"); + Poco::Logger * default_logger; + std::unordered_map tag_loggers; }; class S3AuthSigner : public Aws::Client::AWSAuthV4Signer @@ -102,8 +128,10 @@ public: private: const DB::HeaderCollection headers; }; + } + namespace DB { namespace ErrorCodes From 370dd3396bb1e8cd2301ab9b0e6791954b906cbe Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Wed, 15 Jul 2020 16:18:53 +0200 Subject: [PATCH 102/143] Fixing clang build. --- src/Storages/LiveView/StorageLiveView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Storages/LiveView/StorageLiveView.cpp b/src/Storages/LiveView/StorageLiveView.cpp index 3d2e9657439..3a6dd86e63e 100644 --- a/src/Storages/LiveView/StorageLiveView.cpp +++ b/src/Storages/LiveView/StorageLiveView.cpp @@ -334,8 +334,8 @@ bool StorageLiveView::getNewBlocks() /// called before writeIntoLiveView function is called which can lead to /// the same block added twice to the mergeable_blocks leading to /// inserted data to be duplicated - auto _mergeable_blocks = collectMergeableBlocks(*live_view_context); - Pipes from = blocksToPipes(_mergeable_blocks->blocks, _mergeable_blocks->sample_block); + auto new_mergeable_blocks = collectMergeableBlocks(*live_view_context); + Pipes from = blocksToPipes(new_mergeable_blocks->blocks, new_mergeable_blocks->sample_block); BlockInputStreamPtr data = completeQuery(std::move(from)); while (Block block = data->read()) From de7b0c2424faa0540cb5ffbcc394364be974baa5 Mon Sep 17 00:00:00 2001 From: Anton Popov Date: Wed, 15 Jul 2020 17:22:54 +0300 Subject: [PATCH 103/143] better exception for function 'in' with invalid number of arguments --- src/Interpreters/ActionsVisitor.cpp | 4 ++-- .../ExecuteScalarSubqueriesVisitor.cpp | 2 +- .../MarkTableIdentifiersVisitor.cpp | 2 +- src/Interpreters/misc.h | 21 +++++++++++++++++++ .../01397_in_bad_arguments.reference | 0 .../0_stateless/01397_in_bad_arguments.sql | 4 ++++ 6 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 tests/queries/0_stateless/01397_in_bad_arguments.reference create mode 100644 tests/queries/0_stateless/01397_in_bad_arguments.sql diff --git a/src/Interpreters/ActionsVisitor.cpp b/src/Interpreters/ActionsVisitor.cpp index 512319375d5..f7abfe8950c 100644 --- a/src/Interpreters/ActionsVisitor.cpp +++ b/src/Interpreters/ActionsVisitor.cpp @@ -368,7 +368,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data & } SetPtr prepared_set; - if (functionIsInOrGlobalInOperator(node.name)) + if (checkFunctionIsInOrGlobalInOperator(node)) { /// Let's find the type of the first argument (then getActionsImpl will be called again and will not affect anything). visit(node.arguments->children.at(0), data); @@ -445,7 +445,7 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data & /// Select the name in the next cycle. argument_names.emplace_back(); } - else if (functionIsInOrGlobalInOperator(node.name) && arg == 1 && prepared_set) + else if (checkFunctionIsInOrGlobalInOperator(node) && arg == 1 && prepared_set) { ColumnWithTypeAndName column; column.type = std::make_shared(); diff --git a/src/Interpreters/ExecuteScalarSubqueriesVisitor.cpp b/src/Interpreters/ExecuteScalarSubqueriesVisitor.cpp index e2884d99516..ee29d301c6b 100644 --- a/src/Interpreters/ExecuteScalarSubqueriesVisitor.cpp +++ b/src/Interpreters/ExecuteScalarSubqueriesVisitor.cpp @@ -180,7 +180,7 @@ void ExecuteScalarSubqueriesMatcher::visit(const ASTFunction & func, ASTPtr & as /// But if an argument is not subquery, than deeper may be scalar subqueries and we need to descend in them. std::vector out; - if (functionIsInOrGlobalInOperator(func.name)) + if (checkFunctionIsInOrGlobalInOperator(func)) { for (auto & child : ast->children) { diff --git a/src/Interpreters/MarkTableIdentifiersVisitor.cpp b/src/Interpreters/MarkTableIdentifiersVisitor.cpp index c7b8701c4a0..7ebe12754dc 100644 --- a/src/Interpreters/MarkTableIdentifiersVisitor.cpp +++ b/src/Interpreters/MarkTableIdentifiersVisitor.cpp @@ -35,7 +35,7 @@ void MarkTableIdentifiersMatcher::visit(ASTTableExpression & table, ASTPtr &, Da void MarkTableIdentifiersMatcher::visit(const ASTFunction & func, ASTPtr &, Data & data) { /// `IN t` can be specified, where t is a table, which is equivalent to `IN (SELECT * FROM t)`. - if (functionIsInOrGlobalInOperator(func.name)) + if (checkFunctionIsInOrGlobalInOperator(func)) { auto & ast = func.arguments->children.at(1); auto opt_name = tryGetIdentifierName(ast); diff --git a/src/Interpreters/misc.h b/src/Interpreters/misc.h index 30379567366..094dfbbbb81 100644 --- a/src/Interpreters/misc.h +++ b/src/Interpreters/misc.h @@ -1,10 +1,16 @@ #pragma once #include +#include namespace DB { +namespace ErrorCodes +{ + extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; +} + inline bool functionIsInOperator(const std::string & name) { return name == "in" || name == "notIn" || name == "nullIn" || name == "notNullIn"; @@ -30,4 +36,19 @@ inline bool functionIsDictGet(const std::string & name) return startsWith(name, "dictGet") || (name == "dictHas") || (name == "dictIsIn"); } +inline bool checkFunctionIsInOrGlobalInOperator(const ASTFunction & func) +{ + if (functionIsInOrGlobalInOperator(func.name)) + { + size_t num_arguments = func.arguments->children.size(); + if (num_arguments != 2) + throw Exception("Wrong number of arguments passed to function in. Expected: 2, passed: " + std::to_string(num_arguments), + ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + + return true; + } + + return false; +} + } diff --git a/tests/queries/0_stateless/01397_in_bad_arguments.reference b/tests/queries/0_stateless/01397_in_bad_arguments.reference new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/queries/0_stateless/01397_in_bad_arguments.sql b/tests/queries/0_stateless/01397_in_bad_arguments.sql new file mode 100644 index 00000000000..4854abad091 --- /dev/null +++ b/tests/queries/0_stateless/01397_in_bad_arguments.sql @@ -0,0 +1,4 @@ +select in((1, 1, 1, 1)); -- { serverError 42 } +select in(1); -- { serverError 42 } +select in(); -- { serverError 42 } +select in(1, 2, 3); -- { serverError 42 } From 4892706d950f76e61122f19bd9f381b2e5091b0d Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 17:40:51 +0300 Subject: [PATCH 104/143] Simplify build configuration --- docker/test/fasttest/run.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index d65d21cdef8..9abed794916 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -24,11 +24,11 @@ else fi fi -SUBMODULES_TO_UPDATE="contrib/boost contrib/zlib-ng contrib/libxml2 contrib/poco contrib/libunwind contrib/ryu contrib/fmtlib contrib/base64 contrib/cctz contrib/libcpuid contrib/replxx contrib/double-conversion contrib/libcxx contrib/libcxxabi contrib/libc-headers contrib/lz4 contrib/zstd contrib/fastops contrib/rapidjson contrib/re2 contrib/sparsehash-c11" +SUBMODULES_TO_UPDATE="contrib/boost contrib/zlib-ng contrib/libxml2 contrib/poco contrib/libunwind contrib/ryu contrib/fmtlib contrib/base64 contrib/cctz contrib/libcpuid contrib/double-conversion contrib/libcxx contrib/libcxxabi contrib/libc-headers contrib/lz4 contrib/zstd contrib/fastops contrib/rapidjson contrib/re2 contrib/sparsehash-c11" git submodule update --init --recursive $SUBMODULES_TO_UPDATE | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/submodule_log.txt -export CMAKE_LIBS_CONFIG="-DENABLE_RDKAFKA=0 -DENABLE_S3=0 -DUSE_SENTRY=0 -DENABLE_AMQPCPP=0 -DENABLE_HDFS=0 -DENABLE_MYSQL=0 -DENABLE_GRPC=0 -DENABLE_CURL=0 -DENABLE_JEMALLOC=0 -DENABLE_CAPNP=0 -DENABLE_RDKAFKA=0 -DENABLE_ICU=0 -DENABLE_POCO_NETSSL=0 -DENABLE_ODBC=0 -DENABLE_MYSQL=0 -DENABLE_SSL=0 -DENABLE_POCO_NETSSL=0 -DENABLE_CASSANDRA=0 -DENABLE_PARQUET=0 -DENABLE_AVRO=0 -DENABLE_EMBEDDED_COMPILER=0 -DENABLE_PROTOBUF=0 -DENABLE_H3=0 -DENABLE_TESTS=0 -DENABLE_UTILS=0 -DENABLE_ODBC=0 -DENABLE_GSASL_LIBRARY=0 -DENABLE_THINLTO=0 -DENABLE_MSGPACK=0 -DENABLE_LDAP=0 -DUSE_SNAPPY=0 -DENABLE_HYPERSCAN=0" +export CMAKE_LIBS_CONFIG="-DENABLE_LIBRARIES=0 -DENABLE_TESTS=0 -DENABLE_UTILS=0 -DENABLE_EMBEDDED_COMPILER=0 -DENABLE_THINLTO=0 -DUSE_UNWIND=1" export CCACHE_DIR=/ccache export CCACHE_BASEDIR=/ClickHouse @@ -90,7 +90,7 @@ do sleep 0.1 done -TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading" +TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading base64 01031_mutations_interpreter_and_context json client 01305_replica_create_drop_zookeeper 01092_memory_profiler 01355_ilike" clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt From 74181a30ae22858fd03fb2e5ff221731d67229a7 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 17:56:21 +0300 Subject: [PATCH 105/143] One more test to skip --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 9abed794916..d2a65b94996 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -90,7 +90,7 @@ do sleep 0.1 done -TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading base64 01031_mutations_interpreter_and_context json client 01305_replica_create_drop_zookeeper 01092_memory_profiler 01355_ilike" +TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading base64 01031_mutations_interpreter_and_context json client 01305_replica_create_drop_zookeeper 01092_memory_profiler 01355_ilike 01281_unsucceeded_insert_select_queries_counter" clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt From b558aae8517182abb2246d8b8f10255a7a66fcdc Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Wed, 15 Jul 2020 19:10:47 +0300 Subject: [PATCH 106/143] disable profiler --- tests/performance/decimal_aggregates.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/performance/decimal_aggregates.xml b/tests/performance/decimal_aggregates.xml index 3c210240ab3..33a9ad9e4e7 100644 --- a/tests/performance/decimal_aggregates.xml +++ b/tests/performance/decimal_aggregates.xml @@ -1,6 +1,8 @@ 30G + 0 + 0 CREATE TABLE t (x UInt64, d32 Decimal32(3), d64 Decimal64(4), d128 Decimal128(5)) ENGINE = Memory From e1e22042791459e5ba1db0c4a5fe0836c03981c6 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Wed, 15 Jul 2020 19:37:52 +0300 Subject: [PATCH 107/143] Whitespace --- src/Storages/StorageReplicatedMergeTree.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Storages/StorageReplicatedMergeTree.cpp b/src/Storages/StorageReplicatedMergeTree.cpp index cd7a8f3d39d..c6dc3e67b80 100644 --- a/src/Storages/StorageReplicatedMergeTree.cpp +++ b/src/Storages/StorageReplicatedMergeTree.cpp @@ -4498,7 +4498,11 @@ void StorageReplicatedMergeTree::getReplicaDelays(time_t & out_absolute_delay, t } -void StorageReplicatedMergeTree::fetchPartition(const ASTPtr & partition, const StorageMetadataPtr & metadata_snapshot, const String & from_, const Context & query_context) +void StorageReplicatedMergeTree::fetchPartition( + const ASTPtr & partition, + const StorageMetadataPtr & metadata_snapshot, + const String & from_, + const Context & query_context) { String partition_id = getPartitionIDFromQuery(partition, query_context); From 1426a708bc73c905c1506a85ce5a96ce1e7c9145 Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Wed, 15 Jul 2020 18:45:50 +0200 Subject: [PATCH 108/143] Fixing tests to support changing configuration via server restart. --- tests/testflows/ldap/tests/common.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/testflows/ldap/tests/common.py b/tests/testflows/ldap/tests/common.py index a27013b1797..a1f823550f3 100644 --- a/tests/testflows/ldap/tests/common.py +++ b/tests/testflows/ldap/tests/common.py @@ -79,13 +79,20 @@ def add_config(config, timeout=20, restart=False): time.sleep(1) assert exitcode == 0, error() -# if restart: -# with When("I restart ClickHouse to apply the config changes"): -# node.restart(safe=False) + if restart: + bash.close() + logsize = node.command("ls -s --block-size=1 /var/log/clickhouse-server/clickhouse-server.log").output.split(" ")[0].strip() + with When("I restart ClickHouse to apply the config changes"): + node.restart(safe=False) + bash.prompt = bash.__class__.prompt + bash.open() + bash.send(f"tail -c +{logsize} -f /var/log/clickhouse-server/clickhouse-server.log") with When("I wait for config to be loaded"): - started = time.time() - bash.expect(f"ConfigReloader: Loaded config '/etc/clickhouse-server/{config.preprocessed_name}', performed update on configuration", timeout=timeout) + if restart: + bash.expect(f"ConfigReloader: Loaded config '/etc/clickhouse-server/config.xml', performed update on configuration", timeout=timeout) + else: + bash.expect(f"ConfigReloader: Loaded config '/etc/clickhouse-server/{config.preprocessed_name}', performed update on configuration", timeout=timeout) yield finally: with Finally(f"I remove {config.name}"): From d6da417e7124bda40902715f8f6d082b1c3ac0e0 Mon Sep 17 00:00:00 2001 From: alesapin Date: Wed, 15 Jul 2020 22:34:44 +0300 Subject: [PATCH 109/143] Disable live view tests --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index d2a65b94996..711b1b04556 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -90,7 +90,7 @@ do sleep 0.1 done -TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading base64 01031_mutations_interpreter_and_context json client 01305_replica_create_drop_zookeeper 01092_memory_profiler 01355_ilike 01281_unsucceeded_insert_select_queries_counter" +TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading base64 01031_mutations_interpreter_and_context json client 01305_replica_create_drop_zookeeper 01092_memory_profiler 01355_ilike 01281_unsucceeded_insert_select_queries_counter live_view" clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt From 0ef9fc9022e81e224c7359b5cfe065ccca4b39d3 Mon Sep 17 00:00:00 2001 From: Vitaliy Zakaznikov Date: Wed, 15 Jul 2020 22:13:43 +0200 Subject: [PATCH 110/143] Moving to TestFlows version 1.6.39 --- docker/test/testflows/runner/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/testflows/runner/Dockerfile b/docker/test/testflows/runner/Dockerfile index b922864fefd..f5498535f32 100644 --- a/docker/test/testflows/runner/Dockerfile +++ b/docker/test/testflows/runner/Dockerfile @@ -35,7 +35,7 @@ RUN apt-get update \ ENV TZ=Europe/Moscow RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone -RUN pip3 install urllib3 testflows==1.6.24 docker-compose docker dicttoxml kazoo tzlocal +RUN pip3 install urllib3 testflows==1.6.39 docker-compose docker dicttoxml kazoo tzlocal ENV DOCKER_CHANNEL stable ENV DOCKER_VERSION 17.09.1-ce From d148857d619ae14261c4ecfe0fdf967570a61ebc Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 00:08:51 +0300 Subject: [PATCH 111/143] Added results for Google Pixel --- website/benchmark/hardware/index.html | 3 +- .../hardware/results/047_dell_xps.json | 56 ++++++++++++++++++ .../hardware/results/048_pixel_3a.json | 57 +++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 website/benchmark/hardware/results/047_dell_xps.json create mode 100644 website/benchmark/hardware/results/048_pixel_3a.json diff --git a/website/benchmark/hardware/index.html b/website/benchmark/hardware/index.html index 88ddb2d0868..2e277d94c6a 100644 --- a/website/benchmark/hardware/index.html +++ b/website/benchmark/hardware/index.html @@ -65,7 +65,8 @@ Results for AMD EPYC 7702 are from Peng Gao in sina.com.
Results for Intel NUC are from Alexander Zaitsev, Altinity.
Xeon Gold 6230 server is using 4 x SAMSUNG datacenter class SSD in RAID-10.
Results for Yandex Managed ClickHouse for "cold cache" are biased and should not be compared, because cache was not flushed for every next query.
-Results for AWS Lightsail is from Vamsi Krishna B. +Results for AWS Lightsail is from Vamsi Krishna B.
+Results for Dell XPS laptop and Google Pixel phone is from Alexander Kuzmenkov.

diff --git a/website/benchmark/hardware/results/047_dell_xps.json b/website/benchmark/hardware/results/047_dell_xps.json new file mode 100644 index 00000000000..7d531c99601 --- /dev/null +++ b/website/benchmark/hardware/results/047_dell_xps.json @@ -0,0 +1,56 @@ +[ + { + "system": "Dell XPS 15", + "system_full": "Dell XPS 15, 6 cores, 32 GB RAM", + "cpu_vendor": "Intel", + "cpu_model": "i7-8750H CPU @ 2.20GHz", + "time":"2020-07-15 00:00:00", + "kind":"laptop", + "result": + [ + [0.026, 0.029, 0.001], + [0.087, 0.055, 0.020], + [0.106, 0.065, 0.063], + [0.163, 0.110, 0.107], + [0.312, 0.268, 0.262], + [0.481, 0.449, 0.436], + [0.037, 0.030, 0.024], + [0.024, 0.028, 0.019], + [0.691, 0.622, 0.629], + [0.865, 0.744, 0.742], + [0.364, 0.361, 0.330], + [0.375, 0.341, 0.334], + [1.119, 1.045, 1.055], + [1.445, 1.350, 1.329], + [1.129, 1.040, 1.081], + [1.272, 1.187, 1.239], + [2.854, 2.655, 2.659], + [2.073, 1.673, 1.635], + [5.835, 5.486, 5.675], + [0.220, 0.113, 0.119], + [1.901, 1.753, 1.752], + [2.206, 2.023, 1.996], + [4.556, 4.155, 4.143], + [3.025, 2.424, 2.411], + [0.550, 0.436, 0.427], + [0.418, 0.371, 0.353], + [0.556, 0.438, 0.426], + [2.275, 2.122, 2.094], + [2.594, 2.548, 2.494], + [3.739, 3.788, 3.783], + [1.086, 0.956, 0.962], + [1.908, 1.564, 1.542], + [8.627, 8.810, 8.552], + [6.310, 5.995, 6.061], + [6.197, 6.148, 6.098], + [1.995, 1.916, 1.924], + [0.025, 0.012, 0.006], + [0.005, 0.013, 0.006], + [0.006, 0.004, 0.004], + [0.008, 0.011, 0.005], + [0.009, 0.007, 0.006], + [0.005, 0.007, 0.004], + [0.005, 0.007, 0.011], + ] + } +] diff --git a/website/benchmark/hardware/results/048_pixel_3a.json b/website/benchmark/hardware/results/048_pixel_3a.json new file mode 100644 index 00000000000..1ba5f4e3b3b --- /dev/null +++ b/website/benchmark/hardware/results/048_pixel_3a.json @@ -0,0 +1,57 @@ +[ + { + "system": "Google Pixel 3a", + "system_full": "Google Pixel 3a, 8 cores, 4 GB RAM", + "cpu_vendor": "Qualcomm", + "cpu_model": "Snapdragon 670", + "time": "2020-07-15 00:00:00", + "kind": "phone", + "result": + [ + [0.027, 0.032, 0.023], + [0.214, 0.243, 0.272], + [0.498, 0.369, 0.427], + [0.796, 0.549, 0.546], + [1.032, 1.056, 1.073], + [1.961, 1.913, 1.997], + [0.424, 0.403, 0.405], + [0.275, 0.464, 0.245], + [2.622, 2.620, 2.515], + [3.044, 3.038, 3.014], + [1.788, 1.874, 1.917], + [1.639, 1.664, 1.652], + [null], + [null], + [5.833, 5.118, 5.167], + [5.307, 5.238, 5.350], + [null], + [null], + [null], + [0.818, 0.509, 0.609], + [6.339, 6.158, 6.137], + [7.109, 6.939, 6.970], + [null], + [null], + [2.112, 1.781, 1.724], + [1.493, 1.447, 1.470], + [1.874, 1.792, 1.777], + [6.916, 6.621, 6.670], + [9.732, 9.943, 9.433], + [null], + [4.333, 3.707, 3.740], + [6.902, 7.630, 7.492], + [null], + [null], + [null], + [null], + [0.077, 0.039, 0.034], + [0.047, 0.038, 0.041], + [0.040, 0.037, 0.037], + [0.069, 0.047, 0.043], + [0.055, 0.040, 0.046], + [0.053, 0.038, 0.047], + [0.048, 0.031, 0.034], + ] + } +] + From 37aa2240e6de7f5c556dfd73d588dc81515ce91b Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Thu, 16 Jul 2020 00:09:56 +0300 Subject: [PATCH 112/143] Update 047_dell_xps.json --- website/benchmark/hardware/results/047_dell_xps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/benchmark/hardware/results/047_dell_xps.json b/website/benchmark/hardware/results/047_dell_xps.json index 7d531c99601..0ae08cab25a 100644 --- a/website/benchmark/hardware/results/047_dell_xps.json +++ b/website/benchmark/hardware/results/047_dell_xps.json @@ -4,8 +4,8 @@ "system_full": "Dell XPS 15, 6 cores, 32 GB RAM", "cpu_vendor": "Intel", "cpu_model": "i7-8750H CPU @ 2.20GHz", - "time":"2020-07-15 00:00:00", - "kind":"laptop", + "time": "2020-07-15 00:00:00", + "kind": "laptop", "result": [ [0.026, 0.029, 0.001], From ed9e9c496f5ce2c3651153f00967e01220be0471 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Thu, 16 Jul 2020 00:11:37 +0300 Subject: [PATCH 113/143] Update index.html --- website/benchmark/hardware/index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/benchmark/hardware/index.html b/website/benchmark/hardware/index.html index 2e277d94c6a..8db3a28ba3d 100644 --- a/website/benchmark/hardware/index.html +++ b/website/benchmark/hardware/index.html @@ -66,7 +66,8 @@ Results for Intel NUC are from Alexander Zaitsev, Altinity.
Xeon Gold 6230 server is using 4 x SAMSUNG datacenter class SSD in RAID-10.
Results for Yandex Managed ClickHouse for "cold cache" are biased and should not be compared, because cache was not flushed for every next query.
Results for AWS Lightsail is from Vamsi Krishna B.
-Results for Dell XPS laptop and Google Pixel phone is from Alexander Kuzmenkov. +Results for Dell XPS laptop and Google Pixel phone is from Alexander Kuzmenkov.
+Results for Android phones for "cold cache" are done without cache flushing, so they are not "cold" and cannot be compared.

From 402d03e80ed98f161a6eb9522e6870deb2f7b392 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Thu, 16 Jul 2020 00:47:14 +0300 Subject: [PATCH 114/143] Update 048_pixel_3a.json --- .../hardware/results/048_pixel_3a.json | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/website/benchmark/hardware/results/048_pixel_3a.json b/website/benchmark/hardware/results/048_pixel_3a.json index 1ba5f4e3b3b..98822f93347 100644 --- a/website/benchmark/hardware/results/048_pixel_3a.json +++ b/website/benchmark/hardware/results/048_pixel_3a.json @@ -20,30 +20,30 @@ [3.044, 3.038, 3.014], [1.788, 1.874, 1.917], [1.639, 1.664, 1.652], - [null], - [null], + [null, null, null], + [null, null, null], [5.833, 5.118, 5.167], [5.307, 5.238, 5.350], - [null], - [null], - [null], + [null, null, null], + [null, null, null], + [null, null, null], [0.818, 0.509, 0.609], [6.339, 6.158, 6.137], [7.109, 6.939, 6.970], - [null], - [null], + [null, null, null], + [null, null, null], [2.112, 1.781, 1.724], [1.493, 1.447, 1.470], [1.874, 1.792, 1.777], [6.916, 6.621, 6.670], [9.732, 9.943, 9.433], - [null], + [null, null, null], [4.333, 3.707, 3.740], [6.902, 7.630, 7.492], - [null], - [null], - [null], - [null], + [null, null, null], + [null, null, null], + [null, null, null], + [null, null, null], [0.077, 0.039, 0.034], [0.047, 0.038, 0.041], [0.040, 0.037, 0.037], From deb852f39ff06035bc16d92aa339045f89051b20 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Thu, 16 Jul 2020 00:47:31 +0300 Subject: [PATCH 115/143] Update 048_pixel_3a.json --- website/benchmark/hardware/results/048_pixel_3a.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/benchmark/hardware/results/048_pixel_3a.json b/website/benchmark/hardware/results/048_pixel_3a.json index 98822f93347..d219f41f785 100644 --- a/website/benchmark/hardware/results/048_pixel_3a.json +++ b/website/benchmark/hardware/results/048_pixel_3a.json @@ -50,7 +50,7 @@ [0.069, 0.047, 0.043], [0.055, 0.040, 0.046], [0.053, 0.038, 0.047], - [0.048, 0.031, 0.034], + [0.048, 0.031, 0.034] ] } ] From 9bb32ac7ab1cfbdea6c68d63dc53298675f52437 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Thu, 16 Jul 2020 00:47:43 +0300 Subject: [PATCH 116/143] Update 047_dell_xps.json --- website/benchmark/hardware/results/047_dell_xps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/benchmark/hardware/results/047_dell_xps.json b/website/benchmark/hardware/results/047_dell_xps.json index 0ae08cab25a..828f743cbc9 100644 --- a/website/benchmark/hardware/results/047_dell_xps.json +++ b/website/benchmark/hardware/results/047_dell_xps.json @@ -50,7 +50,7 @@ [0.008, 0.011, 0.005], [0.009, 0.007, 0.006], [0.005, 0.007, 0.004], - [0.005, 0.007, 0.011], + [0.005, 0.007, 0.011] ] } ] From e1173bc3f70df70ae2b7fdf5c0cee5fb89b5b17a Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 05:00:21 +0300 Subject: [PATCH 117/143] Fixup --- src/Common/ZooKeeper/TestKeeper.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Common/ZooKeeper/TestKeeper.cpp b/src/Common/ZooKeeper/TestKeeper.cpp index 6e408750099..1b203d92fb8 100644 --- a/src/Common/ZooKeeper/TestKeeper.cpp +++ b/src/Common/ZooKeeper/TestKeeper.cpp @@ -433,7 +433,8 @@ std::pair TestKeeperMultiRequest::process(TestKeeper::Contain response.error = cur_response->error; for (auto it = undo_actions.rbegin(); it != undo_actions.rend(); ++it) - (*it)(); + if (*it) + (*it)(); return { std::make_shared(response), {} }; } @@ -447,7 +448,8 @@ std::pair TestKeeperMultiRequest::process(TestKeeper::Contain catch (...) { for (auto it = undo_actions.rbegin(); it != undo_actions.rend(); ++it) - (*it)(); + if (*it) + (*it)(); throw; } } From 83b2db4e5b4141820a64e1f29e9ce04074d201a6 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 05:09:02 +0300 Subject: [PATCH 118/143] Fixup --- src/AggregateFunctions/AggregateFunctionAvg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AggregateFunctions/AggregateFunctionAvg.h b/src/AggregateFunctions/AggregateFunctionAvg.h index 73b250547ea..f7bc228bcdd 100644 --- a/src/AggregateFunctions/AggregateFunctionAvg.h +++ b/src/AggregateFunctions/AggregateFunctionAvg.h @@ -75,7 +75,7 @@ public: { writeBinary(this->data(place).numerator, buf); - if constexpr (std::is_integral_v) + if constexpr (std::is_unsigned_v) writeVarUInt(this->data(place).denominator, buf); else /// Floating point denominator type can be used writeBinary(this->data(place).denominator, buf); @@ -85,7 +85,7 @@ public: { readBinary(this->data(place).numerator, buf); - if constexpr (std::is_integral_v) + if constexpr (std::is_unsigned_v) readVarUInt(this->data(place).denominator, buf); else /// Floating point denominator type can be used readBinary(this->data(place).denominator, buf); From 11f8e2d90654d592f264b956aa756cebd27a8261 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 05:11:40 +0300 Subject: [PATCH 119/143] Remove strange empty file --- .../test_backward_compatability/test_string_aggregation.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/integration/test_backward_compatability/test_string_aggregation.py diff --git a/tests/integration/test_backward_compatability/test_string_aggregation.py b/tests/integration/test_backward_compatability/test_string_aggregation.py deleted file mode 100644 index e69de29bb2d..00000000000 From 8abcee3201e59b735292a1278d50c2ba69c4d391 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 05:27:46 +0300 Subject: [PATCH 120/143] Add integration test --- .../__init__.py | 0 .../test.py | 0 .../test_aggregate_function_state_avg.py | 52 +++++++++++++++++++ .../test_short_strings_aggregation.py | 0 4 files changed, 52 insertions(+) rename tests/integration/{test_backward_compatability => test_backward_compatibility}/__init__.py (100%) rename tests/integration/{test_backward_compatability => test_backward_compatibility}/test.py (100%) create mode 100644 tests/integration/test_backward_compatibility/test_aggregate_function_state_avg.py rename tests/integration/{test_backward_compatability => test_backward_compatibility}/test_short_strings_aggregation.py (100%) diff --git a/tests/integration/test_backward_compatability/__init__.py b/tests/integration/test_backward_compatibility/__init__.py similarity index 100% rename from tests/integration/test_backward_compatability/__init__.py rename to tests/integration/test_backward_compatibility/__init__.py diff --git a/tests/integration/test_backward_compatability/test.py b/tests/integration/test_backward_compatibility/test.py similarity index 100% rename from tests/integration/test_backward_compatability/test.py rename to tests/integration/test_backward_compatibility/test.py diff --git a/tests/integration/test_backward_compatibility/test_aggregate_function_state_avg.py b/tests/integration/test_backward_compatibility/test_aggregate_function_state_avg.py new file mode 100644 index 00000000000..e8c5323f845 --- /dev/null +++ b/tests/integration/test_backward_compatibility/test_aggregate_function_state_avg.py @@ -0,0 +1,52 @@ +import pytest + +import helpers.client as client +from helpers.cluster import ClickHouseCluster + +cluster = ClickHouseCluster(__file__) +node1 = cluster.add_instance('node1', + with_zookeeper=False, image='yandex/clickhouse-server:19.16.9.37', stay_alive=True, with_installed_binary=True) +node2 = cluster.add_instance('node2', + with_zookeeper=False, image='yandex/clickhouse-server:19.16.9.37', stay_alive=True, with_installed_binary=True) +node3 = cluster.add_instance('node3', with_zookeeper=False) +node4 = cluster.add_instance('node4', with_zookeeper=False) + +@pytest.fixture(scope="module") +def start_cluster(): + try: + cluster.start() + yield cluster + + finally: + cluster.shutdown() + +# We will test that serialization of internal state of "avg" function is compatible between different versions. +# TODO Implement versioning of serialization format for aggregate function states. +# NOTE This test is too ad-hoc. + +def test_backward_compatability(start_cluster): + node1.query("create table tab (x UInt64) engine = Memory") + node2.query("create table tab (x UInt64) engine = Memory") + node3.query("create table tab (x UInt64) engine = Memory") + node4.query("create table tab (x UInt64) engine = Memory") + + node1.query("INSERT INTO tab VALUES (1)") + node2.query("INSERT INTO tab VALUES (2)") + node3.query("INSERT INTO tab VALUES (3)") + node4.query("INSERT INTO tab VALUES (4)") + + assert(node1.query("SELECT avg(x) FROM remote('node{1..4}', default, tab)") == '2.5\n') + assert(node2.query("SELECT avg(x) FROM remote('node{1..4}', default, tab)") == '2.5\n') + assert(node3.query("SELECT avg(x) FROM remote('node{1..4}', default, tab)") == '2.5\n') + assert(node4.query("SELECT avg(x) FROM remote('node{1..4}', default, tab)") == '2.5\n') + + # Also check with persisted aggregate function state + + node1.query("create table tab (x AggregateFunction(avg, UInt32)) engine = Log") + node1.query("INSERT INTO tab SELECT avgState(arrayJoin([1, 2, 3, 4]))") + + assert(node1.query("SELECT avgMerge(x) FROM tab") == '2.5\n') + + node1.restart_with_latest_version() + + assert(node1.query("SELECT avgMerge(x) FROM tab") == '2.5\n') diff --git a/tests/integration/test_backward_compatability/test_short_strings_aggregation.py b/tests/integration/test_backward_compatibility/test_short_strings_aggregation.py similarity index 100% rename from tests/integration/test_backward_compatability/test_short_strings_aggregation.py rename to tests/integration/test_backward_compatibility/test_short_strings_aggregation.py From 2753cb58b6aa4362e8b2a1d2d6d4c84a9176a34d Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 05:31:03 +0300 Subject: [PATCH 121/143] Fixup --- .../test_aggregate_function_state_avg.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/integration/test_backward_compatibility/test_aggregate_function_state_avg.py b/tests/integration/test_backward_compatibility/test_aggregate_function_state_avg.py index e8c5323f845..c9f3acc2e2e 100644 --- a/tests/integration/test_backward_compatibility/test_aggregate_function_state_avg.py +++ b/tests/integration/test_backward_compatibility/test_aggregate_function_state_avg.py @@ -42,11 +42,11 @@ def test_backward_compatability(start_cluster): # Also check with persisted aggregate function state - node1.query("create table tab (x AggregateFunction(avg, UInt32)) engine = Log") - node1.query("INSERT INTO tab SELECT avgState(arrayJoin([1, 2, 3, 4]))") + node1.query("create table state (x AggregateFunction(avg, UInt64)) engine = Log") + node1.query("INSERT INTO state SELECT avgState(arrayJoin(CAST([1, 2, 3, 4] AS Array(UInt64))))") - assert(node1.query("SELECT avgMerge(x) FROM tab") == '2.5\n') + assert(node1.query("SELECT avgMerge(x) FROM state") == '2.5\n') node1.restart_with_latest_version() - assert(node1.query("SELECT avgMerge(x) FROM tab") == '2.5\n') + assert(node1.query("SELECT avgMerge(x) FROM state") == '2.5\n') From a6016b95ce4410b63b0a59bdc70a189c03e730bf Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 05:34:43 +0300 Subject: [PATCH 122/143] Fix clang-tidy --- src/Disks/IDisk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Disks/IDisk.cpp b/src/Disks/IDisk.cpp index 8ac3bacd6e3..9d7424d1286 100644 --- a/src/Disks/IDisk.cpp +++ b/src/Disks/IDisk.cpp @@ -47,7 +47,7 @@ void IDisk::copy(const String & from_path, const std::shared_ptr & to_dis } } -void IDisk::truncateFile(const String & path, size_t size) +void IDisk::truncateFile(const String &, size_t) { throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Truncate operation is not implemented for disk of type {}", getType()); } From 82ea884d01939f7a2fd5f53a45e00c48e42537af Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 05:37:12 +0300 Subject: [PATCH 123/143] Fix incorrect unit test --- src/Storages/tests/gtest_storage_log.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Storages/tests/gtest_storage_log.cpp b/src/Storages/tests/gtest_storage_log.cpp index a9a4ea4ad0e..13c96fbab54 100644 --- a/src/Storages/tests/gtest_storage_log.cpp +++ b/src/Storages/tests/gtest_storage_log.cpp @@ -100,6 +100,7 @@ std::string writeData(int rows, DB::StoragePtr & table, const DB::Context & cont BlockOutputStreamPtr out = table->write({}, metadata_snapshot, context); out->write(block); + out->writeSuffix(); return data; } @@ -115,7 +116,8 @@ std::string readData(DB::StoragePtr & table, const DB::Context & context) QueryProcessingStage::Enum stage = table->getQueryProcessingStage(context); - BlockInputStreamPtr in = std::make_shared(std::move(table->read(column_names, metadata_snapshot, {}, context, stage, 8192, 1)[0])); + BlockInputStreamPtr in = std::make_shared( + std::move(table->read(column_names, metadata_snapshot, {}, context, stage, 8192, 1)[0])); Block sample; { From 68f9fd3767077a2ef724d057086188bf90c93b14 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 06:02:20 +0300 Subject: [PATCH 124/143] Debug tests --- src/Storages/StorageTinyLog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Storages/StorageTinyLog.cpp b/src/Storages/StorageTinyLog.cpp index 3d2c20e6b50..2c83c2ebad4 100644 --- a/src/Storages/StorageTinyLog.cpp +++ b/src/Storages/StorageTinyLog.cpp @@ -118,14 +118,14 @@ public: { try { - std::cerr << "Done: " << done << "\n"; + LOG_TRACE(storage.log, "Done: {}\n", done); if (!done) { /// Rollback partial writes. streams.clear(); - std::cerr << "Repairing\n"; + LOG_TRACE(storage.log, "Repairing"); storage.file_checker.repair(); } From 1e8f340e2272b45072ffdde81959ee2593c2a066 Mon Sep 17 00:00:00 2001 From: Ivan Blinkov Date: Thu, 16 Jul 2020 10:17:00 +0300 Subject: [PATCH 125/143] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 0585667dcc2..1dfdf450d8a 100644 --- a/README.md +++ b/README.md @@ -16,5 +16,4 @@ ClickHouse is an open-source column-oriented database management system that all ## Upcoming Events -* [ClickHouse virtual office hours](https://www.eventbrite.com/e/clickhouse-july-virtual-meetup-tickets-111199787558) on July 15, 2020. * [ClickHouse at ByteDance (in Chinese)](https://mp.weixin.qq.com/s/Em-HjPylO8D7WPui4RREAQ) on July 17, 2020. From 6df282e81397680c9f8fd5f40bf1108764d13c93 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 16 Jul 2020 11:33:51 +0300 Subject: [PATCH 126/143] Fixup --- src/Common/FileChecker.cpp | 4 ++-- src/Disks/DiskLocal.cpp | 2 +- src/Storages/StorageTinyLog.cpp | 5 ----- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Common/FileChecker.cpp b/src/Common/FileChecker.cpp index c8e5a039cde..6cbec3bda77 100644 --- a/src/Common/FileChecker.cpp +++ b/src/Common/FileChecker.cpp @@ -82,8 +82,8 @@ void FileChecker::repair() const String & name = name_size.first; size_t expected_size = name_size.second; String path = parentPath(files_info_path) + name; - - auto real_size = disk->exists(path) ? disk->getFileSize(path) : 0; /// Race condition is Ok. + bool exists = disk->exists(path); + auto real_size = exists ? disk->getFileSize(path) : 0; /// No race condition assuming no one else is working with these files. if (real_size < expected_size) throw Exception(ErrorCodes::UNEXPECTED_END_OF_FILE, "Size of {} is less than expected. Size is {} but should be {}.", diff --git a/src/Disks/DiskLocal.cpp b/src/Disks/DiskLocal.cpp index f8c1342a2ae..f9e988211da 100644 --- a/src/Disks/DiskLocal.cpp +++ b/src/Disks/DiskLocal.cpp @@ -264,7 +264,7 @@ void DiskLocal::createHardLink(const String & src_path, const String & dst_path) void DiskLocal::truncateFile(const String & path, size_t size) { - int res = truncate(path.c_str(), size); + int res = truncate((disk_path + path).c_str(), size); if (-1 == res) throwFromErrnoWithPath("Cannot truncate file " + path, path, ErrorCodes::CANNOT_TRUNCATE_FILE); } diff --git a/src/Storages/StorageTinyLog.cpp b/src/Storages/StorageTinyLog.cpp index 2c83c2ebad4..b68ac6ae5f1 100644 --- a/src/Storages/StorageTinyLog.cpp +++ b/src/Storages/StorageTinyLog.cpp @@ -118,15 +118,10 @@ public: { try { - LOG_TRACE(storage.log, "Done: {}\n", done); - if (!done) { /// Rollback partial writes. streams.clear(); - - LOG_TRACE(storage.log, "Repairing"); - storage.file_checker.repair(); } } From ff372ec0f0535975a6086f783cf0bb6f5f5fb63d Mon Sep 17 00:00:00 2001 From: Artem Zuikov Date: Thu, 16 Jul 2020 11:56:45 +0300 Subject: [PATCH 127/143] Standard join type syntax position (#12520) --- docs/en/engines/table-engines/special/join.md | 2 +- docs/en/operations/settings/settings.md | 2 +- .../sql-reference/statements/select/join.md | 14 ++--- docs/es/engines/table-engines/special/join.md | 2 +- .../sql-reference/statements/select/join.md | 12 ++--- docs/fa/engines/table-engines/special/join.md | 2 +- .../sql-reference/statements/select/join.md | 11 ++-- docs/fr/engines/table-engines/special/join.md | 2 +- .../sql-reference/statements/select/join.md | 12 ++--- docs/ja/engines/table-engines/special/join.md | 2 +- docs/ru/engines/table-engines/special/join.md | 2 +- .../sql-reference/statements/select/join.md | 14 ++--- docs/tr/engines/table-engines/special/join.md | 2 +- docs/zh/engines/table-engines/special/join.md | 2 +- .../sql-reference/statements/select/join.md | 12 ++--- src/Interpreters/HashJoin.cpp | 3 +- src/Parsers/ParserTablesInSelectQuery.cpp | 53 ++++++++++++------- src/Parsers/ParserTablesInSelectQuery.h | 4 ++ .../01332_join_type_syntax_position.reference | 12 +++++ .../01332_join_type_syntax_position.sql | 31 +++++++++++ 20 files changed, 117 insertions(+), 79 deletions(-) create mode 100644 tests/queries/0_stateless/01332_join_type_syntax_position.reference create mode 100644 tests/queries/0_stateless/01332_join_type_syntax_position.sql diff --git a/docs/en/engines/table-engines/special/join.md b/docs/en/engines/table-engines/special/join.md index b8c3a6c83f1..0572627473e 100644 --- a/docs/en/engines/table-engines/special/join.md +++ b/docs/en/engines/table-engines/special/join.md @@ -24,7 +24,7 @@ See the detailed description of the [CREATE TABLE](../../../sql-reference/statem **Engine Parameters** -- `join_strictness` – [JOIN strictness](../../../sql-reference/statements/select/join.md#select-join-strictness). +- `join_strictness` – [JOIN strictness](../../../sql-reference/statements/select/join.md#select-join-types). - `join_type` – [JOIN type](../../../sql-reference/statements/select/join.md#select-join-types). - `k1[, k2, ...]` – Key columns from the `USING` clause that the `JOIN` operation is made with. diff --git a/docs/en/operations/settings/settings.md b/docs/en/operations/settings/settings.md index 1944573230c..da6c6519b36 100644 --- a/docs/en/operations/settings/settings.md +++ b/docs/en/operations/settings/settings.md @@ -471,7 +471,7 @@ Default value: 0. See also: -- [JOIN strictness](../../sql-reference/statements/select/join.md#select-join-strictness) +- [JOIN strictness](../../sql-reference/statements/select/join.md#join-settings) ## temporary\_files\_codec {#temporary_files_codec} diff --git a/docs/en/sql-reference/statements/select/join.md b/docs/en/sql-reference/statements/select/join.md index 0b42ed1a0d2..7d41930aab6 100644 --- a/docs/en/sql-reference/statements/select/join.md +++ b/docs/en/sql-reference/statements/select/join.md @@ -11,7 +11,7 @@ Syntax: ``` sql SELECT FROM -[GLOBAL] [ANY|ALL|ASOF] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI] JOIN +[GLOBAL] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI|ANY|ASOF] JOIN (ON )|(USING ) ... ``` @@ -33,17 +33,13 @@ Additional join types available in ClickHouse: - `LEFT SEMI JOIN` and `RIGHT SEMI JOIN`, a whitelist on “join keys”, without producing a cartesian product. - `LEFT ANTI JOIN` and `RIGHT ANTI JOIN`, a blacklist on “join keys”, without producing a cartesian product. +- `LEFT ANY JOIN`, `RIGHT ANY JOIN` and `INNER ANY JOIN`, partially (for opposite side of `LEFT` and `RIGHT`) or completely (for `INNER` and `FULL`) disables the cartesian product for standard `JOIN` types. +- `ASOF JOIN` and `LEFT ASOF JOIN`, joining sequences with a non-exact match. `ASOF JOIN` usage is described below. -## Strictness {#select-join-strictness} - -Modifies how matching by “join keys” is performed - -- `ALL` — The standard `JOIN` behavior in SQL as described above. The default. -- `ANY` — Partially (for opposite side of `LEFT` and `RIGHT`) or completely (for `INNER` and `FULL`) disables the cartesian product for standard `JOIN` types. -- `ASOF` — For joining sequences with a non-exact match. `ASOF JOIN` usage is described below. +## Setting {#join-settings} !!! note "Note" - The default strictness value can be overriden using [join\_default\_strictness](../../../operations/settings/settings.md#settings-join_default_strictness) setting. + The default join type can be overriden using [join\_default\_strictness](../../../operations/settings/settings.md#settings-join_default_strictness) setting. Also the behavior of ClickHouse server for `ANY JOIN` operations depends on the [any_join_distinct_right_table_keys](../../../operations/settings/settings.md#any_join_distinct_right_table_keys) setting. diff --git a/docs/es/engines/table-engines/special/join.md b/docs/es/engines/table-engines/special/join.md index bb8b0e513d9..a553a0d24ef 100644 --- a/docs/es/engines/table-engines/special/join.md +++ b/docs/es/engines/table-engines/special/join.md @@ -23,7 +23,7 @@ Vea la descripción detallada del [CREATE TABLE](../../../sql-reference/statemen **Parámetros del motor** -- `join_strictness` – [ÚNETE a la rigurosidad](../../../sql-reference/statements/select/join.md#select-join-strictness). +- `join_strictness` – [ÚNETE a la rigurosidad](../../../sql-reference/statements/select/join.md#select-join-types). - `join_type` – [Tipo de unión](../../../sql-reference/statements/select/join.md#select-join-types). - `k1[, k2, ...]` – Key columns from the `USING` cláusula que el `JOIN` operación se hace con. diff --git a/docs/es/sql-reference/statements/select/join.md b/docs/es/sql-reference/statements/select/join.md index 986cd3a11a3..158731d679c 100644 --- a/docs/es/sql-reference/statements/select/join.md +++ b/docs/es/sql-reference/statements/select/join.md @@ -12,7 +12,7 @@ Sintaxis: ``` sql SELECT FROM -[GLOBAL] [ANY|ALL|ASOF] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI] JOIN +[GLOBAL] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI|ANY|ASOF] JOIN (ON )|(USING ) ... ``` @@ -34,14 +34,10 @@ Tipos de unión adicionales disponibles en ClickHouse: - `LEFT SEMI JOIN` y `RIGHT SEMI JOIN`, una lista blanca en “join keys”, sin producir un producto cartesiano. - `LEFT ANTI JOIN` y `RIGHT ANTI JOIN`, una lista negra sobre “join keys”, sin producir un producto cartesiano. +- `LEFT ANY JOIN`, `RIGHT ANY JOIN` and `INNER ANY JOIN`, partially (for opposite side of `LEFT` and `RIGHT`) or completely (for `INNER` and `FULL`) disables the cartesian product for standard `JOIN` types. +- `ASOF JOIN` and `LEFT ASOF JOIN`, joining sequences with a non-exact match. `ASOF JOIN` usage is described below. -## Rigor {#select-join-strictness} - -Modifica cómo coincidir por “join keys” se realiza - -- `ALL` — The standard `JOIN` comportamiento en SQL como se describió anteriormente. Predeterminado. -- `ANY` — Partially (for opposite side of `LEFT` y `RIGHT`) o completamente (para `INNER` y `FULL`) deshabilita el producto cartesiano para `JOIN` tipo. -- `ASOF` — For joining sequences with a non-exact match. `ASOF JOIN` el uso se describe a continuación. +## Setting {#join-settings} !!! note "Nota" El valor de rigor predeterminado se puede anular usando [Por favor, introduzca su dirección de correo electrónico](../../../operations/settings/settings.md#settings-join_default_strictness) configuración. diff --git a/docs/fa/engines/table-engines/special/join.md b/docs/fa/engines/table-engines/special/join.md index d35246b5fc3..07518b5b897 100644 --- a/docs/fa/engines/table-engines/special/join.md +++ b/docs/fa/engines/table-engines/special/join.md @@ -23,7 +23,7 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] **پارامترهای موتور** -- `join_strictness` – [پیوستن به سختی](../../../sql-reference/statements/select/join.md#select-join-strictness). +- `join_strictness` – [پیوستن به سختی](../../../sql-reference/statements/select/join.md#select-join-types). - `join_type` – [پیوستن به نوع](../../../sql-reference/statements/select/join.md#select-join-types). - `k1[, k2, ...]` – Key columns from the `USING` بند که `JOIN` عملیات با ساخته شده. diff --git a/docs/fa/sql-reference/statements/select/join.md b/docs/fa/sql-reference/statements/select/join.md index 21e19c124fd..c77049fb280 100644 --- a/docs/fa/sql-reference/statements/select/join.md +++ b/docs/fa/sql-reference/statements/select/join.md @@ -12,7 +12,7 @@ machine_translated_rev: 72537a2d527c63c07aa5d2361a8829f3895cf2bd ``` sql SELECT FROM -[GLOBAL] [ANY|ALL|ASOF] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI] JOIN +[GLOBAL] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI|ANY|ASOF] JOIN (ON )|(USING ) ... ``` @@ -34,15 +34,12 @@ FROM - `LEFT SEMI JOIN` و `RIGHT SEMI JOIN`, یک لیست سفید در “join keys”, بدون تولید محصول دکارتی. - `LEFT ANTI JOIN` و `RIGHT ANTI JOIN`, لیست سیاه در “join keys”, بدون تولید محصول دکارتی. +- `LEFT ANY JOIN`, `RIGHT ANY JOIN` و `INNER ANY JOIN`, partially (for opposite side of `LEFT` and `RIGHT`) or completely (for `INNER` and `FULL`) disables the cartesian product for standard `JOIN` types. +- `ASOF JOIN` و `LEFT ASOF JOIN`, joining sequences with a non-exact match. `ASOF JOIN` usage is described below. -## سختی {#select-join-strictness} +## Setting {#join-settings} تغییر چگونگی تطبیق توسط “join keys” انجام شده است - -- `ALL` — The standard `JOIN` رفتار در گذاشتن همانطور که در بالا توضیح. به طور پیش فرض. -- `ANY` — Partially (for opposite side of `LEFT` و `RIGHT`) یا به طور کامل (برای `INNER` و `FULL`) غیر فعال محصول دکارتی برای استاندارد `JOIN` انواع. -- `ASOF` — For joining sequences with a non-exact match. `ASOF JOIN` استفاده در زیر توضیح داده شده است. - !!! note "یادداشت" مقدار سختگیرانه پیش فرض را می توان با استفاده از لغو [بررسی اجمالی](../../../operations/settings/settings.md#settings-join_default_strictness) تنظیمات. diff --git a/docs/fr/engines/table-engines/special/join.md b/docs/fr/engines/table-engines/special/join.md index a3b33a7aa32..01b14911e26 100644 --- a/docs/fr/engines/table-engines/special/join.md +++ b/docs/fr/engines/table-engines/special/join.md @@ -23,7 +23,7 @@ Voir la description détaillée de la [CREATE TABLE](../../../sql-reference/stat **Les Paramètres Du Moteur** -- `join_strictness` – [ADHÉRER à la rigueur](../../../sql-reference/statements/select/join.md#select-join-strictness). +- `join_strictness` – [ADHÉRER à la rigueur](../../../sql-reference/statements/select/join.md#select-join-types). - `join_type` – [Type de jointure](../../../sql-reference/statements/select/join.md#select-join-types). - `k1[, k2, ...]` – Key columns from the `USING` la clause que l' `JOIN` l'opération est faite avec de la. diff --git a/docs/fr/sql-reference/statements/select/join.md b/docs/fr/sql-reference/statements/select/join.md index d802f68e4bf..335086349d3 100644 --- a/docs/fr/sql-reference/statements/select/join.md +++ b/docs/fr/sql-reference/statements/select/join.md @@ -12,7 +12,7 @@ Syntaxe: ``` sql SELECT FROM -[GLOBAL] [ANY|ALL|ASOF] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI] JOIN +[GLOBAL] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI|ANY|ASOF] JOIN (ON )|(USING ) ... ``` @@ -34,14 +34,10 @@ Autres types de jointure disponibles dans ClickHouse: - `LEFT SEMI JOIN` et `RIGHT SEMI JOIN` une liste blanche sur “join keys”, sans produire un produit cartésien. - `LEFT ANTI JOIN` et `RIGHT ANTI JOIN` une liste noire sur “join keys”, sans produire un produit cartésien. +- `LEFT ANY JOIN`, `RIGHT ANY JOIN` et `INNER ANY JOIN`, partially (for opposite side of `LEFT` and `RIGHT`) or completely (for `INNER` and `FULL`) disables the cartesian product for standard `JOIN` types. +- `ASOF JOIN` et `LEFT ASOF JOIN`, joining sequences with a non-exact match. `ASOF JOIN` usage is described below. -## Rigueur {#select-join-strictness} - -Modifie la façon dont la correspondance par “join keys” est effectué - -- `ALL` — The standard `JOIN` comportement en SQL comme décrit ci-dessus. Défaut. -- `ANY` — Partially (for opposite side of `LEFT` et `RIGHT`) ou complètement (pour `INNER` et `FULL`) désactive le produit cartésien de la norme `JOIN` type. -- `ASOF` — For joining sequences with a non-exact match. `ASOF JOIN` l'utilisation est décrite ci-dessous. +## Setting {#join-settings} !!! note "Note" La valeur de rigueur par défaut peut être remplacée à l'aide [join\_default\_strictness](../../../operations/settings/settings.md#settings-join_default_strictness) paramètre. diff --git a/docs/ja/engines/table-engines/special/join.md b/docs/ja/engines/table-engines/special/join.md index 4a3cc351e51..e88bc12a484 100644 --- a/docs/ja/engines/table-engines/special/join.md +++ b/docs/ja/engines/table-engines/special/join.md @@ -23,7 +23,7 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] **エンジン変数** -- `join_strictness` – [厳密に結合する](../../../sql-reference/statements/select/join.md#select-join-strictness). +- `join_strictness` – [厳密に結合する](../../../sql-reference/statements/select/join.md#select-join-types). - `join_type` – [結合タイプ](../../../sql-reference/statements/select/join.md#select-join-types). - `k1[, k2, ...]` – Key columns from the `USING` 句は、 `JOIN` 操作はでなされる。 diff --git a/docs/ru/engines/table-engines/special/join.md b/docs/ru/engines/table-engines/special/join.md index a5ed68f0959..2caf1187d50 100644 --- a/docs/ru/engines/table-engines/special/join.md +++ b/docs/ru/engines/table-engines/special/join.md @@ -16,7 +16,7 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] **Параметры движка** -- `join_strictness` – [строгость JOIN](../../../engines/table-engines/special/join.md#select-join-strictness). +- `join_strictness` – [строгость JOIN](../../../engines/table-engines/special/join.md#select-join-types). - `join_type` – [тип JOIN](../../../engines/table-engines/special/join.md#select-join-types). - `k1[, k2, ...]` – ключевые столбцы секции `USING` с которыми выполняется операция `JOIN`. diff --git a/docs/ru/sql-reference/statements/select/join.md b/docs/ru/sql-reference/statements/select/join.md index 26e7ae8257e..de5e3cdb76c 100644 --- a/docs/ru/sql-reference/statements/select/join.md +++ b/docs/ru/sql-reference/statements/select/join.md @@ -7,7 +7,7 @@ Join создаёт новую таблицу путем объединения ``` sql SELECT FROM -[GLOBAL] [ANY|ALL|ASOF] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI] JOIN +[GLOBAL] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI|ANY|ASOF] JOIN (ON )|(USING ) ... ``` @@ -29,18 +29,14 @@ FROM - `LEFT SEMI JOIN` и `RIGHT SEMI JOIN`, белый список по ключам соединения, не производит декартово произведение. - `LEFT ANTI JOIN` и `RIGHT ANTI JOIN`, черный список по ключам соединения, не производит декартово произведение. +- `LEFT ANY JOIN`, `RIGHT ANY JOIN` и `INNER ANY JOIN`, Частично (для противоположных сторон `LEFT` и `RIGHT`) или полностью (для `INNER` и `FULL`) отключает декартово произведение для стандартых видов `JOIN`. +- `ASOF JOIN` и `LEFT ASOF JOIN`, Для соединения последовательностей по нечеткому совпадению. Использование `ASOF JOIN` описано ниже. -## Строгость {#select-join-strictness} - -Изменяет способ сопоставления по ключам соединения: - -- `ALL` — стандартное поведение `JOIN` в SQL, как описано выше. По умолчанию. -- `ANY` — Частично (для противоположных сторон `LEFT` и `RIGHT`) или полностью (для `INNER` и `FULL`) отключает декартово произведение для стандартых видов `JOIN`. -- `ASOF` — Для соединения последовательностей по нечеткому совпадению. Использование `ASOF JOIN` описано ниже. +## Настройки {#join-settings} !!! note "Примечание" Значение строгости по умолчанию может быть переопределено с помощью настройки [join\_default\_strictness](../../../operations/settings/settings.md#settings-join_default_strictness). - + ### Использование ASOF JOIN {#asof-join-usage} `ASOF JOIN` применим в том случае, когда необходимо объединять записи, которые не имеют точного совпадения. diff --git a/docs/tr/engines/table-engines/special/join.md b/docs/tr/engines/table-engines/special/join.md index bc9182d9823..f7605f1b579 100644 --- a/docs/tr/engines/table-engines/special/join.md +++ b/docs/tr/engines/table-engines/special/join.md @@ -23,7 +23,7 @@ Ayrıntılı açıklamasına bakın [CREATE TABLE](../../../sql-reference/statem **Motor Parametreleri** -- `join_strictness` – [Katılık katılın](../../../sql-reference/statements/select/join.md#select-join-strictness). +- `join_strictness` – [Katılık katılın](../../../sql-reference/statements/select/join.md#select-join-types). - `join_type` – [Birleştirme türü](../../../sql-reference/statements/select/join.md#select-join-types). - `k1[, k2, ...]` – Key columns from the `USING` fık thera: `JOIN` işlemi yapılmamaktadır. diff --git a/docs/zh/engines/table-engines/special/join.md b/docs/zh/engines/table-engines/special/join.md index a94803a401b..22e67ba46d5 100644 --- a/docs/zh/engines/table-engines/special/join.md +++ b/docs/zh/engines/table-engines/special/join.md @@ -24,7 +24,7 @@ CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster] **引擎参数** -- `join_strictness` – [JOIN 限制](../../../sql-reference/statements/select/join.md#select-join-strictness). +- `join_strictness` – [JOIN 限制](../../../sql-reference/statements/select/join.md#select-join-types). - `join_type` – [JOIN 类型](../../../sql-reference/statements/select/join.md#select-join-types). - `k1[, k2, ...]` – 进行`JOIN` 操作时 `USING`语句用到的key列 diff --git a/docs/zh/sql-reference/statements/select/join.md b/docs/zh/sql-reference/statements/select/join.md index 47fd0137717..355ed0e617c 100644 --- a/docs/zh/sql-reference/statements/select/join.md +++ b/docs/zh/sql-reference/statements/select/join.md @@ -13,7 +13,7 @@ Join通过使用一个或多个表的公共值合并来自一个或多个表的 ``` sql SELECT FROM -[GLOBAL] [ANY|ALL|ASOF] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI] JOIN +[GLOBAL] [INNER|LEFT|RIGHT|FULL|CROSS] [OUTER|SEMI|ANTI|ANY|ASOF] JOIN (ON )|(USING ) ... ``` @@ -35,14 +35,10 @@ ClickHouse中提供的其他联接类型: - `LEFT SEMI JOIN` 和 `RIGHT SEMI JOIN`,白名单 “join keys”,而不产生笛卡尔积。 - `LEFT ANTI JOIN` 和 `RIGHT ANTI JOIN`,黑名单 “join keys”,而不产生笛卡尔积。 +- `LEFT ANY JOIN`, `RIGHT ANY JOIN` and `INNER ANY JOIN`, partially (for opposite side of `LEFT` and `RIGHT`) or completely (for `INNER` and `FULL`) disables the cartesian product for standard `JOIN` types. +- `ASOF JOIN` and `LEFT ASOF JOIN`, joining sequences with a non-exact match. `ASOF JOIN` usage is described below. -## 严格 {#select-join-strictness} - -修改如何匹配 “join keys” 执行 - -- `ALL` — The standard `JOIN` sql中的行为如上所述。 默认值。 -- `ANY` — Partially (for opposite side of `LEFT` 和 `RIGHT`)或完全(为 `INNER` 和 `FULL`)禁用笛卡尔积为标准 `JOIN` 类型。 -- `ASOF` — For joining sequences with a non-exact match. `ASOF JOIN` 用法描述如下。 +## 严格 {#join-settings} !!! note "注" 可以使用以下方式复盖默认的严格性值 [join\_default\_strictness](../../../operations/settings/settings.md#settings-join_default_strictness) 设置。 diff --git a/src/Interpreters/HashJoin.cpp b/src/Interpreters/HashJoin.cpp index 5549d636a48..27294a57675 100644 --- a/src/Interpreters/HashJoin.cpp +++ b/src/Interpreters/HashJoin.cpp @@ -39,6 +39,7 @@ namespace ErrorCodes extern const int INCOMPATIBLE_TYPE_OF_JOIN; extern const int UNSUPPORTED_JOIN_KEYS; extern const int LOGICAL_ERROR; + extern const int SYNTAX_ERROR; extern const int SET_SIZE_LIMIT_EXCEEDED; extern const int TYPE_MISMATCH; } @@ -174,7 +175,7 @@ HashJoin::HashJoin(std::shared_ptr table_join_, const Block & right_s key_columns.pop_back(); if (key_columns.empty()) - throw Exception("ASOF join cannot be done without a joining column", ErrorCodes::LOGICAL_ERROR); + throw Exception("ASOF join cannot be done without a joining column", ErrorCodes::SYNTAX_ERROR); /// this is going to set up the appropriate hash table for the direct lookup part of the join /// However, this does not depend on the size of the asof join key (as that goes into the BST) diff --git a/src/Parsers/ParserTablesInSelectQuery.cpp b/src/Parsers/ParserTablesInSelectQuery.cpp index 7e84925b203..a13baf69420 100644 --- a/src/Parsers/ParserTablesInSelectQuery.cpp +++ b/src/Parsers/ParserTablesInSelectQuery.cpp @@ -103,6 +103,20 @@ bool ParserArrayJoin::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) } +void ParserTablesInSelectQueryElement::parseJoinStrictness(Pos & pos, ASTTableJoin & table_join) +{ + if (ParserKeyword("ANY").ignore(pos)) + table_join.strictness = ASTTableJoin::Strictness::Any; + else if (ParserKeyword("ALL").ignore(pos)) + table_join.strictness = ASTTableJoin::Strictness::All; + else if (ParserKeyword("ASOF").ignore(pos)) + table_join.strictness = ASTTableJoin::Strictness::Asof; + else if (ParserKeyword("SEMI").ignore(pos)) + table_join.strictness = ASTTableJoin::Strictness::Semi; + else if (ParserKeyword("ANTI").ignore(pos) || ParserKeyword("ONLY").ignore(pos)) + table_join.strictness = ASTTableJoin::Strictness::Anti; +} + bool ParserTablesInSelectQueryElement::parseImpl(Pos & pos, ASTPtr & node, Expected & expected) { auto res = std::make_shared(); @@ -131,19 +145,12 @@ bool ParserTablesInSelectQueryElement::parseImpl(Pos & pos, ASTPtr & node, Expec else if (ParserKeyword("LOCAL").ignore(pos)) table_join->locality = ASTTableJoin::Locality::Local; - if (ParserKeyword("ANY").ignore(pos)) - table_join->strictness = ASTTableJoin::Strictness::Any; - else if (ParserKeyword("ALL").ignore(pos)) - table_join->strictness = ASTTableJoin::Strictness::All; - else if (ParserKeyword("ASOF").ignore(pos)) - table_join->strictness = ASTTableJoin::Strictness::Asof; - else if (ParserKeyword("SEMI").ignore(pos)) - table_join->strictness = ASTTableJoin::Strictness::Semi; - else if (ParserKeyword("ANTI").ignore(pos) || ParserKeyword("ONLY").ignore(pos)) - table_join->strictness = ASTTableJoin::Strictness::Anti; - else - table_join->strictness = ASTTableJoin::Strictness::Unspecified; + table_join->strictness = ASTTableJoin::Strictness::Unspecified; + /// Legacy: allow JOIN type before JOIN kind + parseJoinStrictness(pos, *table_join); + + bool no_kind = false; if (ParserKeyword("INNER").ignore(pos)) table_join->kind = ASTTableJoin::Kind::Inner; else if (ParserKeyword("LEFT").ignore(pos)) @@ -155,6 +162,20 @@ bool ParserTablesInSelectQueryElement::parseImpl(Pos & pos, ASTPtr & node, Expec else if (ParserKeyword("CROSS").ignore(pos)) table_join->kind = ASTTableJoin::Kind::Cross; else + no_kind = true; + + /// Standard position: JOIN type after JOIN kind + parseJoinStrictness(pos, *table_join); + + /// Optional OUTER keyword for outer joins. + if (table_join->kind == ASTTableJoin::Kind::Left + || table_join->kind == ASTTableJoin::Kind::Right + || table_join->kind == ASTTableJoin::Kind::Full) + { + ParserKeyword("OUTER").ignore(pos); + } + + if (no_kind) { /// Use INNER by default as in another DBMS. if (table_join->strictness == ASTTableJoin::Strictness::Semi || @@ -172,14 +193,6 @@ bool ParserTablesInSelectQueryElement::parseImpl(Pos & pos, ASTPtr & node, Expec (table_join->kind != ASTTableJoin::Kind::Left && table_join->kind != ASTTableJoin::Kind::Right)) throw Exception("SEMI|ANTI JOIN should be LEFT or RIGHT.", ErrorCodes::SYNTAX_ERROR); - /// Optional OUTER keyword for outer joins. - if (table_join->kind == ASTTableJoin::Kind::Left - || table_join->kind == ASTTableJoin::Kind::Right - || table_join->kind == ASTTableJoin::Kind::Full) - { - ParserKeyword("OUTER").ignore(pos); - } - if (!ParserKeyword("JOIN").ignore(pos, expected)) return false; } diff --git a/src/Parsers/ParserTablesInSelectQuery.h b/src/Parsers/ParserTablesInSelectQuery.h index 82e4c3c171c..9e5b591ccbe 100644 --- a/src/Parsers/ParserTablesInSelectQuery.h +++ b/src/Parsers/ParserTablesInSelectQuery.h @@ -6,6 +6,8 @@ namespace DB { +struct ASTTableJoin; + /** List of single or multiple JOIN-ed tables or subqueries in SELECT query, with ARRAY JOINs and SAMPLE, FINAL modifiers. */ class ParserTablesInSelectQuery : public IParserBase @@ -27,6 +29,8 @@ protected: private: bool is_first; + + static void parseJoinStrictness(Pos & pos, ASTTableJoin & table_join); }; diff --git a/tests/queries/0_stateless/01332_join_type_syntax_position.reference b/tests/queries/0_stateless/01332_join_type_syntax_position.reference new file mode 100644 index 00000000000..66f4ca4a5a8 --- /dev/null +++ b/tests/queries/0_stateless/01332_join_type_syntax_position.reference @@ -0,0 +1,12 @@ +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 diff --git a/tests/queries/0_stateless/01332_join_type_syntax_position.sql b/tests/queries/0_stateless/01332_join_type_syntax_position.sql new file mode 100644 index 00000000000..bb87c7eb425 --- /dev/null +++ b/tests/queries/0_stateless/01332_join_type_syntax_position.sql @@ -0,0 +1,31 @@ +select * from numbers(1) t1 left outer join numbers(1) t2 using number; +select * from numbers(1) t1 right outer join numbers(1) t2 using number; + +select * from numbers(1) t1 left any join numbers(1) t2 using number; +select * from numbers(1) t1 right any join numbers(1) t2 using number; + +select * from numbers(1) t1 left semi join numbers(1) t2 using number; +select * from numbers(1) t1 right semi join numbers(1) t2 using number; + +select * from numbers(1) t1 left anti join numbers(1) t2 using number; +select * from numbers(1) t1 right anti join numbers(1) t2 using number; + +select * from numbers(1) t1 asof join numbers(1) t2 using number; -- { serverError 62 } +select * from numbers(1) t1 left asof join numbers(1) t2 using number; -- { serverError 62 } + +-- legacy + +select * from numbers(1) t1 all left join numbers(1) t2 using number; +select * from numbers(1) t1 all right join numbers(1) t2 using number; + +select * from numbers(1) t1 any left join numbers(1) t2 using number; +select * from numbers(1) t1 any right join numbers(1) t2 using number; + +select * from numbers(1) t1 semi left join numbers(1) t2 using number; +select * from numbers(1) t1 semi right join numbers(1) t2 using number; + +select * from numbers(1) t1 anti left join numbers(1) t2 using number; +select * from numbers(1) t1 anti right join numbers(1) t2 using number; + +select * from numbers(1) t1 asof join numbers(1) t2 using number; -- { serverError 62 } +select * from numbers(1) t1 asof left join numbers(1) t2 using number; -- { serverError 62 } From 21d3a797944066cb0b520e372570717ab165f3c4 Mon Sep 17 00:00:00 2001 From: alesapin Date: Thu, 16 Jul 2020 14:08:26 +0300 Subject: [PATCH 128/143] Fix arcadia build for msgpack --- src/Processors/Formats/Impl/MsgPackRowInputFormat.h | 7 +++++-- src/Processors/Formats/Impl/MsgPackRowOutputFormat.h | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Processors/Formats/Impl/MsgPackRowInputFormat.h b/src/Processors/Formats/Impl/MsgPackRowInputFormat.h index add5c516771..ac44772929a 100644 --- a/src/Processors/Formats/Impl/MsgPackRowInputFormat.h +++ b/src/Processors/Formats/Impl/MsgPackRowInputFormat.h @@ -1,7 +1,10 @@ #pragma once -#include "config_formats.h" -#include "config_core.h" +#if !defined(ARCADIA_BUILD) +# include "config_formats.h" +# include "config_core.h" +#endif + #if USE_MSGPACK diff --git a/src/Processors/Formats/Impl/MsgPackRowOutputFormat.h b/src/Processors/Formats/Impl/MsgPackRowOutputFormat.h index 401fe492f56..00bdfcc21cf 100644 --- a/src/Processors/Formats/Impl/MsgPackRowOutputFormat.h +++ b/src/Processors/Formats/Impl/MsgPackRowOutputFormat.h @@ -1,7 +1,9 @@ #pragma once -#include "config_formats.h" -#include "config_core.h" +#if !defined(ARCADIA_BUILD) +# include "config_formats.h" +# include "config_core.h" +#endif #if USE_MSGPACK From f7ffd2da360cefe41572cad32275e9f07980c724 Mon Sep 17 00:00:00 2001 From: alesapin Date: Thu, 16 Jul 2020 14:12:47 +0300 Subject: [PATCH 129/143] Remove memory limiting tests --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index 711b1b04556..bd2aec03422 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -90,7 +90,7 @@ do sleep 0.1 done -TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading base64 01031_mutations_interpreter_and_context json client 01305_replica_create_drop_zookeeper 01092_memory_profiler 01355_ilike 01281_unsucceeded_insert_select_queries_counter live_view" +TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading base64 01031_mutations_interpreter_and_context json client 01305_replica_create_drop_zookeeper 01092_memory_profiler 01355_ilike 01281_unsucceeded_insert_select_queries_counter live_view limit_memory memory_limit memory_leak" clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt From a4666df09003124fe3efdda91f9579c8b6633f73 Mon Sep 17 00:00:00 2001 From: alesapin Date: Thu, 16 Jul 2020 14:16:08 +0300 Subject: [PATCH 130/143] Even less tests in fasttest --- docker/test/fasttest/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/test/fasttest/run.sh b/docker/test/fasttest/run.sh index bd2aec03422..0254f18030a 100755 --- a/docker/test/fasttest/run.sh +++ b/docker/test/fasttest/run.sh @@ -90,7 +90,7 @@ do sleep 0.1 done -TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading base64 01031_mutations_interpreter_and_context json client 01305_replica_create_drop_zookeeper 01092_memory_profiler 01355_ilike 01281_unsucceeded_insert_select_queries_counter live_view limit_memory memory_limit memory_leak" +TESTS_TO_SKIP="parquet avro h3 odbc mysql sha256 _orc_ arrow 01098_temporary_and_external_tables 01083_expressions_in_engine_arguments hdfs 00911_tautological_compare protobuf capnproto java_hash hashing secure 00490_special_line_separators_and_characters_outside_of_bmp 00436_convert_charset 00105_shard_collations 01354_order_by_tuple_collate_const 01292_create_user 01098_msgpack_format 00929_multi_match_edit_distance 00926_multimatch 00834_cancel_http_readonly_queries_on_client_close brotli parallel_alter 00302_http_compression 00417_kill_query 01294_lazy_database_concurrent 01193_metadata_loading base64 01031_mutations_interpreter_and_context json client 01305_replica_create_drop_zookeeper 01092_memory_profiler 01355_ilike 01281_unsucceeded_insert_select_queries_counter live_view limit_memory memory_limit memory_leak 00110_external_sort 00682_empty_parts_merge 00701_rollup 00109_shard_totals_after_having" clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip $TESTS_TO_SKIP 2>&1 | ts '%Y-%m-%d %H:%M:%S' | tee /test_output/test_log.txt From 7b9354db4b4ca441240362aeae36ae2774add44b Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Thu, 16 Jul 2020 15:01:18 +0300 Subject: [PATCH 131/143] [draft] Pixel benchmark blog post --- website/blog/en/2020/pixel-bencmhark.md | 85 ++++++++++++++++++ .../blog/en/2020/pixel-bencmhark/compare.png | Bin 0 -> 55265 bytes website/blog/en/2020/pixel-bencmhark/main.jpg | Bin 0 -> 29411 bytes .../blog/en/2020/pixel-bencmhark/segfault.png | Bin 0 -> 471124 bytes 4 files changed, 85 insertions(+) create mode 100644 website/blog/en/2020/pixel-bencmhark.md create mode 100644 website/blog/en/2020/pixel-bencmhark/compare.png create mode 100644 website/blog/en/2020/pixel-bencmhark/main.jpg create mode 100644 website/blog/en/2020/pixel-bencmhark/segfault.png diff --git a/website/blog/en/2020/pixel-bencmhark.md b/website/blog/en/2020/pixel-bencmhark.md new file mode 100644 index 00000000000..c2338cc8451 --- /dev/null +++ b/website/blog/en/2020/pixel-bencmhark.md @@ -0,0 +1,85 @@ +--- +title: 'Running ClickHouse on an Android phone' +image: 'pixel-benchmark/main.jpg' +date: '2020-07-16' +author: '[Alexander Kuzmenkov](https://github.com/akuzm)' +tags: ['benchmark'] +--- + +## [draft] Running ClickHouse on an Android phone + +This is a brief description of my experiments with building ClickHouse on Android. If this is your first time hearing about ClickHouse, it is a suriprisingly fast columnar SQL DBMS for real-time reporting. It's normally used in AdTech and the like, deployed on clusters of hundreds of machines, holding up to petabytes of data. But ClickHouse is straightforward to use on a smaller scale as well -- you laptop will do, and don't be surprised if you are able to process several gigabytes of data per second on this hardware. There is another kind of small-scale, though pretty powerful, platforms, that is ubiquitous now -- smartphones. The conclusion inevitably follows: you must be able to run ClickHouse on your smartphone as well. It's also that I can't help but chuckle at the idea of setting up a high performance mobile OLAP cluster using a dozen of phones. Or also at the idea of seeing the nostalgic `Segmentation fault (core dumped)` on the lovely OLED screen, but I digress. Let's get it going. + +### First cheap attempt + +I heard somewhere that Android uses the Linux kernel, and I can already run familiar UNIX-like shell and tools using [Termux](https://termux.com/). And ClickHouse already supports ARM platform and even publishes a binary built for 64-bit ARM. This binary also doesn't have a lot of dependencies -- only a pretty old version of `glibc`. Maybe I can just download a ClickHouse binary from CI to the phone and run it? + +Turns out it's not that simple. + +* First thing we'll see after trying to run is a cryptic message `./clickhouse: file is not found`. But it's right there! `strace` helps: what cannot be found is `/lib64/ld-linux-x86-64.so.2`, a linker specified in the ClickHouse binary. The linker in this case is a system program that initially loads the application binary and its dependencies before passing control to the application. Android uses a different linker located by another path, this is why we get the error. This problem can be overcome if we call the linker explicitly, e.g. `/system/bin/linker64 $(readlink -f ./clickhouse)`. + +* Immediately we encounter another problem -- the linker complains that the binary has a wrong type `ET_EXEC`. What does this mean? Android binaries must support dynamic relocation, so that they can be loaded at any address, probably for ASLR purposes. ClickHouse binaries do not normally use position-independent code, because we have measured that it gives a small performance penalty of about 1%. After tweaking compilation and linking flags to include `-fPIC` as much as possible, and battling some really weird linker errors, we finally arrive at a relocatable binary that has a correct type `ET_DYN`. + +* But it only gets worse. Now it complains about TLS section offset being wrong. After reading some mail archives where I could barely understand a word, I concluded that Android uses some different layout of memory for the section of the executable that holds thread-local variables, and `clang` from Android toolchain is patched to account for this. After that, I had to accept I won't be able to use familiar tools, and reluctantly turned to the Android toolchain. + +### Using the Android toolchain + +Surprisingly, it's rather simple to set up. Our build system uses CMake and already supports cross-compilation -- we have CI configurations that cross-compile for Mac, AArch64 Linux and FreeBSD. Android NDK also has integration with CMake and a [manual](https://developer.android.com/ndk/guides/cmake) on how to set it up. Download the Android NDK, add some flags to your `cmake` invocation: `DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r21d/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28`, and you're done. It (almost) builds. What obstacles do we have this time? + +* Our `glibc` compatibility layer has a lot of compilation errors. It borrows `musl` code to provide functions that are absent from older versions of `glibc`, so that we can run the same binary on a wide range of distros. Being heavily dependent on system headers, it runs into all kinds of differences between Linux and Android, such as the limited scope of `pthread` support or just subtly different API variants. Thankfully we're building for a particular version of Android, so we can just disable this and use all needed functions straight from the system `libc`. +* Some third-party libraries and our CMake files broken in various unimaginative ways. Just disable everything we can and fix everything we can't. +* Some of our code uses `#if defined(__linux__)` to check for Linux platform -- this doesn't always work, because Android also exports `__linux__` but there are some API differences. +* `std::filesystem` is still not fully supported in NDK r21 -- the support went into r22 that is scheduled for Q3 2020, but I want it now... Good that we bundle our own forks of `libcxx` and `libcxxabi` to reduce dependencies, and they are fresh enough to fully support C++20. After enabling them, everything works. +* Weird twenty-screens errors in `std::map` or something like that, that are also resolved by using our `libcxx`. + +### On the device + +At last, we have a binary we can actually run. Copy it to the phone, `chmod +x`, `./clickhouse server --config-path db/config.xml`, run some queries, it works! + + + +Feels soo good to see my favorite message. + +It's a full-fledged development environment here in Termux, let's install `gdb` and attach it to see where the segfault happens. Run `gdb clickhouse --ex run '--config-path ....'`, wait for it to lauch for a minute, only to see how Android kills Termux becase it is out of memory. Are 4 GB of RAM not enough, after all? Looking at the `clickhouse` binary, its size is a whoppping 1.1 GB. The major part of the bloat is due to the fact that some of our computational code is heavily specialized for particular data types (mostly via C++ templates), and also the fact that we build and link a lot of third-party libraries statically. A non-essential part of the binary is debug symbols, which help to produce good stack traces in error messages. We can remove them with `strip -s ./clickhouse` right here on the phone, and after that, the size becomes more manageable, about 400 MB. Finally we can run `gdb` and see that the segfault is somewhere in `unw_backtrace`: + +``` +Thread 60 "ConfigReloader" received signal SIGSEGV, Segmentation fault. +[Switching to LWP 21873] +0x000000556a73f740 in ?? () + +(gdb) whe 20 +#0 0x000000556a73f740 in ?? () +#1 0x000000556a744028 in ?? () +#2 0x000000556a73e5a0 in ?? () +#3 0x000000556a73d250 in unw_init_local () +#4 0x000000556a73deb8 in unw_backtrace () +#5 0x0000005562aabb54 in StackTrace::tryCapture() () +#6 0x0000005562aabb10 in StackTrace::StackTrace() () +#7 0x0000005562a8d73c in MemoryTracker::alloc(long) () +#8 0x0000005562a8db38 in MemoryTracker::alloc(long) () +#9 0x0000005562a8e8bc in CurrentMemoryTracker::alloc(long) () +#10 0x0000005562a8b88c in operator new[](unsigned long) () +#11 0x0000005569c35f08 in Poco::XML::NamePool::NamePool(unsigned long) () +... +``` + +What is this function, and why do we need it? In this particular stack trace, we're out of memory, and about to throw an exception for that. `unw_backtrace` is called to produce a backtrace for the exception message. But there is another interesting context where we call it. Believe it or not, ClickHouse has a built-in `perf`-like sampling profiler that can save stack traces for CPU time and real time, and also memory allocations. The data is saved into a `system.trace_log` table, so you can build flame graphs for what your query was doing as simple as piping output of an SQL query into `flamegraph.pl`. This is an interesting feature, but what is relevant now is that it sends signals to all threads of the server to interrupt them at some random time and save their current backtraces, using the same `unw_backtrace` function that we know to segfault. We expect query profiler to be used in production environment, so it is enabled by default. After disabling it, we have a functioning ClickHouse server running on Android. + +### Is your phone good enough? + +There is a beaten genre of using data sets and queries of a varying degree of syntheticity to prove that a particular DBMS you work on has performance superior to other, less advanced, DBMSes. We've moved past that, and instead use the DBMS we love as a benchmark of hardware. For this benchmark we use a small 100M rows obfuscated data set from Yandex.Metrica, about 12 GB compressed, and some queries representative of Metrica dashboards. There is [this page](https://clickhouse.tech/benchmark/hardware/) with crowdsourced results for various cloud and traditional servers and even some laptops, but how do the phones compare? Let's find out. Following [the manual](https://clickhouse.tech/docs/en/operations/performance-test/) to download the necessary data to the phone and run the benchmark was pretty straightforward. One problem was that some queries can't run because they use too much memory and the server gets killed by Android, so I had to script around that. Also I'm not sure how to reset a file system cache on Android, so the 'cold run' data is not correct. The results look pretty good: + + + +My phone is Google Pixel 3a, and it is only 5 times slower on average than my Dell XPS 15 work laptop. The queries where the data doesn't fit into memory and has to go to disk (the flash, I mean) are noticeably slower, up to 20 times, but mostly they don't complete because the server gets killed -- it only has about 3 GB of memory available. Overall I think the results look pretty good for the phone. High-end models should be even more performant, reaching performance comparable to some smaller laptops. + +### Conclusion + +This was a rather enjoyable exercise. Running a server on your phone is a nice way to give a demo, so we should probably publish a Termux package for ClickHouse. For this, we have to debug and fix the `unw_backtrace` segfault (I have my fingers crossed that it will be gone after adding `-fno-omit-frame-pointer`), and also fix some quirks that are just commented out for now. Most of the changes required for the Android build are already merged into our master branch. + +Building for Android turned out to be relatively simple -- all these experiments and writing took me about four days, and it was the first time I ever did any Android-related programming. The NDK was simple to use, and our code was cross-platform enough so I only had to make minor modifications. If we didn't routinely build for AArch64 and had a hard dependency on SSE 4.2 or something, it would have been a different story. + +But the most important takeout is that now you don't have to obsess over choosing a new phone -- just benchmark it with ClickHouse. + + +_2020-07-16 [Alexander Kuzmenkov](https://github.com/akuzm)_ diff --git a/website/blog/en/2020/pixel-bencmhark/compare.png b/website/blog/en/2020/pixel-bencmhark/compare.png new file mode 100644 index 0000000000000000000000000000000000000000..573d13f67a59440fde7f988974682a563c8958a3 GIT binary patch literal 55265 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

-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 R#F}2yeKj4`vU^q`{|$p2X|(_V literal 0 HcmV?d00001 diff --git a/website/blog/en/2020/pixel-bencmhark/main.jpg b/website/blog/en/2020/pixel-bencmhark/main.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b511a28a96067c4463b49cb92e5260cd9afc2c86 GIT binary patch literal 29411 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 z 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 z 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

KTq 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
t_jAnsSYS$@1Z!P;ZjrSeFgtIn2kt|4NNKJzp8G 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�(=3DkyDS!N-YL|Pwy`}T}} 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

D- zV`LCSD`!Z-3Rwa>?dq$D$M$x1(2fIZw`Qe<%w33!QO%Zvf>RhOzl8(*6%XEq)KWDD zc}2w)yPB4k79?LVy%cKIl-Aa|fxpu!??Z)NhPYwY=`a7zKM=rz_|pAOU2Xac?CHRv zXTj3@Kx^aApAQ(aS;N`;E~>?p%Ht%FOeM04Q?2f4(%_pBKHn^J)85OkdVe`>8Qp{n z@fM4qXM(@dU=b=RDhRwkfByXN;X@Qr;OISJ5hTM|f!HlBx0=vdOw5iCV>Mov&mt)* z9~88Q&!O&M-1Se@m7(Iul#vYTWEMEKv6aTLxkF`i>Oucl!rXq2qu!%&r-!d!Xh<-E zae)5I3PQw(wJms#48hwRx7{$Ic=y0dN-)`vbYP?GK>|rO!5yK8Co~5V{4#_G=2_pF zwBx&ITtt7^&=oQw4jf1h%)0_jaou}lNUwhJJFZ8~;z4H#On#HwpN-b$nyx_=EAa^L z43fP$p~QNV{_tSe-LfYJ=N{qub5}|ImoIb0p4>+#7x zFJET8Ey)OTW_7D`KP2k?gRanV(OqlH4Slf<&(=nk`^AQeR7@R}WpDyo4{gku@9`l- zdgm326fO=1EGfUM9hNPSV$n+B$F$zZph2W6J+~}U&VY8Fdlj1U5$_;-1lG5k!dO)Z z&HfY|OkE+D$U7AEMac7v9v?$(3zWWTY4QJt;99`smi`AOHc;MIydlpQLtfp5+6O8= z*#65S#-(Ce^~Ln{AJz^5+5$I|QVnSF<(PG=Z5~2=7^&Sv7=2!d%u(^q&C`Y@TJ>{a zfQ6A!{Mq0yYmx$1%=4=0{EuyI5^8D1#k&>1bTU3mOG;|j*r6sx$Y#M7&GX-d&O3f= zPwxkP*fV-Os6H`TogLEOccda-Jz{_>`%w;4!d`TKc`&vv{PEe^yxzM)vbDht1-kZ` z=XSaYAJLPoUH^GH4pc@(3bh3n}+#k za`3XXPNT&RtX;yId)7@tk=okzDTQzCpusVZBE_TF__Va)#oT3`b6APO=WWHdS{M0* zdZa+@MvEfdeH+Y#Q7VUxXJl)q|Aw{U(O$6O4BpjZ-tl8*@vaAabh=<;S4yq)b=g-n zZ%x`XP(!Zn>3^6jFSI)90&I~CqLhegu>#pkW-vdLd?>Z%9 zQcB6j`@xzF5|&N(VTxHyL13YBU zB=M-m_RsC_Hc;fQ>RfW>u78-EPnh}jHn$o=&wpUJKaI_e`?gr0E$8kHszR zr!7oQ_6tcFJD1nC6cdc64`CCmJL*6OZtDx$5N&_jq8*lt-cJ7FM(52*&(ZR3Ml$jl zEX9AP>8JKQj~0sR1)3ToNF(A#nnc}>*4f5)Eq0Rs3{J)sd5`SYDi?FALHl3b&V?_t z_40iS$HPs$@;A-&q}&!FMY3LAjYAl~?SY7LEbf`(cYQywHIOD1Ks8WJxZrBD|LwsA zu$+k9i{;gL)8~DCDIJliSuk5|OZ`mcL;%jS2}Ex$>Fa+D z#gdBS!BU)R2p{oPel6wt?MtEfR7y+pH1Uf&$EMGJw12usd+2#`6+_*#Efw)?$~c%0 zhlhWhjZMwRk+IM*U(8W6Xo@Hq8?QprxJW{c)zpu`)Il7zKqumHw+*$SjS>piG4`&t z<)l3NkLoo{#Eh;BDtd~rbB5s$Qh(gpY2Sl`gIykhjU{5ApUj@eJN~~y-)E%_7s^{Z zY=!(%f1_RH-}cvpNjRCqPHe8B4>Kj~yNLPCO@X&< zci@i2#!hXGdZMbd0JSmtX}QGU|8|A_-g(w_rJ!n7OghA^e|Ubo@HIO#b7jFfwV;Jm z6j;wb8veJKGd#{>~pe>Rz|Ag%}PtC+`zb2)Lvw5fMLtcLkS1 zKt#b5PH(Kw#$5azSp5ndZ-OeP-s?iuFMwsm^N(aDhCE!T@{APSD$kzlAbjpBPiwjQ&raHu7!eDreznk!jweF$<&`7- zyMB}u$=yKcIm&|T+*CZ6gSh4vn)QY4l0uOx=0%=)4@NLWR_3g%Tw}IUEP7D0ikQsn z

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

-QvY( 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 ?ZfI zAH>5Ul8yQ=Gl3uFb!r6AWepx;1d9J2RTjy*XoZ#&Fa@BeHd0&%=^YTE_On0bWJ33R z_#SCEP_&z%z(PC%BNv!Ai~vADhAU%#;^X53Zh%Hud8D=aU@8tEaO)mM0nATB#wiuu zxApB33VFD91Jr!k8>tRe9gZ9I&xaggt-npma3*^1cAK(q?32ZqtY&;M6`wl@;Zdr! z$HZ3Dwh0d{sMcRj{T}?%Sf4G#g=BD>>PNHaMz6A~tMW(jA?n3W?V1R5JFnb_iW^b5 z6}vtMX~zwfY#og#6x~N^IC=N){YG&@1%Iuz{q8r6z&%G4Z(XCUE?t5QdeFZlTs+gqI`?q1TR@NV4<)xs78ByT5 zC70JG;`+DtzET&~fd1^ATj{6>J*^0fjMGn5EVVh6ayhCnvBf~^bkG+@ zje`oyH)nRQU)f;J{D0bXjyC>CESM|0jafD^Ht6*%Wue6@s&u ziTp*uDapkymvzIBq;V0+$;IAR%X82SOjN8XkTHVh8wko>U5h1|XfR=zS6}}+vf}pI za(9Yqf?=Y& zxI!=6uE^oswc!XArr${%zYW#t{wUCF5{5KD76T}qw>FLG&Jy*VS|$e|z(LjM2B>2< zFm!ZuV9cB`7!ek>^7}PnZ^pj)xtUpFga+6%!vJIg`4x(zdSuD_o>yd|e zwyuZnh@Ak+EoBr0ubZC@m(v2D%#NyEayag_CekCLN-K)O`FeTyyQw4Ad&<{v^Z>0%5XwY82nj3|r$2kfqCs(lm-RKv>Xf=E#5==%g-P zRWrUld1fb55cjl`?8(!k$Bu7B^G33Bq&K~a)foQ>AL@(!h-&e%R2LScskOEP2|9$H zC=oY+=oLcE%WK7~w08!C{ytV$=z#Tjd2^{uH!^(%MEo-E?YIr&-yb$oVYcl^VLxnr z-)JR(GLwQ8cvxUtz5x4!hG<%=gEUTn8ly<;LHp{ZKe!sh&n>6CXra^DGp3A<9@9sb z8LCrS?_jkXGCI?*aSIGp=i7K}eTnDKt|fxd_*``-J<_wb;W@cSaa)M=PM8`)u2v`u zbE-N04en#KrS*_flMthk)8Il4QZf8=3g2|s&V|qpedw}lYTDV6960{*U5noYJ3h_H z^Gdg%jc&y}j!FoyzX!t2IpED@ONBCkWk8-BAeuY1@_CM16QzL12n`GS;2hP_5=3nKn&r%5t>1=dj!|{tT5{42cv&FS~^n>++|>RDw!#SGReM!pF4Z(8vp7 zNnt!YhLS`Cy|M$x8Z{I5@9gSTmT5MzsRaB#sQ4O`>x;sh@9oF282%D$y7=2*zYeQd zcd9RM?^nK_W#wWCU{A(BFM1(}`APGw`>jM_1nNf#A9BYo^iP@$S5>ad6YnF7&Qy@Y z#Kc9|F2sI}o7P&F(bFo1Vk%3&%F~}KUA^N5t`im(QLn~RMev0{V<0Dc1dNUJ=n5=5 zc9u+RtbE?p>oiGN<_;ik$oz1w1D!%y2eOQxQh6g^3B+V9Or@m6epH)UJ}#;$`|K)_ zcg&ASiU7aA_wP#?JeXB(r*5vV6e)`mHBVo4C4)+*v~z56 zvXl924v+2pOgbPC`{d*vgtPS;9}r_(028l6T-8GT)p%+0J#dK0vdH$&j*ox3IynNt zC{zjHYI*hQz?AP*p+-FjOEG6=rnhXi-Z2-KB`T-KkK9Iu_noU~{^Zz0mu7PE?ptWj z>os^W3A>0}%6>_(_{bSkI&9fNASPkzW_7k|BSqh@6)rh8Hh=0q`e7*YbNAkgkB?

rx!*0m<4<8 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 ZT(;P>;L}UVEF Date: Thu, 16 Jul 2020 15:04:08 +0300 Subject: [PATCH 132/143] Update deploy-to-test.sh --- docs/tools/deploy-to-test.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/tools/deploy-to-test.sh b/docs/tools/deploy-to-test.sh index 769d51cf5c8..ee5bf5f9faf 100755 --- a/docs/tools/deploy-to-test.sh +++ b/docs/tools/deploy-to-test.sh @@ -4,8 +4,9 @@ # This script deploys ClickHouse website to your personal test subdomain. # # Before first use of this script: -# 1) Create https://github.com/GIT_USER/clickhouse.github.io repo (replace GIT_USER with your GitHub login) -# 2) Send email on address from https://clickhouse.tech/#contacts asking to create GIT_USER-test.clickhouse.tech domain +# 1) Set up building documentation according to https://github.com/ClickHouse/ClickHouse/tree/master/docs/tools +# 2) Create https://github.com/GIT_USER/clickhouse.github.io repo (replace GIT_USER with your GitHub login) +# 3) Send email on address from https://clickhouse.tech/#contacts asking to create GIT_USER-test.clickhouse.tech domain # set -ex From 7f5b5fa6ad18df2563fc4c49d99d2693dc862249 Mon Sep 17 00:00:00 2001 From: Ivan Blinkov Date: Thu, 16 Jul 2020 15:05:03 +0300 Subject: [PATCH 133/143] Update deploy-to-test.sh --- docs/tools/deploy-to-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tools/deploy-to-test.sh b/docs/tools/deploy-to-test.sh index ee5bf5f9faf..a7fc98bb620 100755 --- a/docs/tools/deploy-to-test.sh +++ b/docs/tools/deploy-to-test.sh @@ -4,7 +4,7 @@ # This script deploys ClickHouse website to your personal test subdomain. # # Before first use of this script: -# 1) Set up building documentation according to https://github.com/ClickHouse/ClickHouse/tree/master/docs/tools +# 1) Set up building documentation according to https://github.com/ClickHouse/ClickHouse/tree/master/docs/tools#use-buildpy-use-build-py # 2) Create https://github.com/GIT_USER/clickhouse.github.io repo (replace GIT_USER with your GitHub login) # 3) Send email on address from https://clickhouse.tech/#contacts asking to create GIT_USER-test.clickhouse.tech domain # From 2d9c110ebe2de05a679f5773e6d71c401c729a2e Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 16 Jul 2020 16:08:52 +0300 Subject: [PATCH 134/143] Apply suggestions from code review Co-authored-by: Ivan Blinkov --- website/blog/en/2020/pixel-bencmhark.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/website/blog/en/2020/pixel-bencmhark.md b/website/blog/en/2020/pixel-bencmhark.md index c2338cc8451..70e93be1226 100644 --- a/website/blog/en/2020/pixel-bencmhark.md +++ b/website/blog/en/2020/pixel-bencmhark.md @@ -3,14 +3,14 @@ title: 'Running ClickHouse on an Android phone' image: 'pixel-benchmark/main.jpg' date: '2020-07-16' author: '[Alexander Kuzmenkov](https://github.com/akuzm)' -tags: ['benchmark'] +tags: ['Android', 'benchmark', 'experiment'] --- -## [draft] Running ClickHouse on an Android phone +# Running ClickHouse on an Android phone This is a brief description of my experiments with building ClickHouse on Android. If this is your first time hearing about ClickHouse, it is a suriprisingly fast columnar SQL DBMS for real-time reporting. It's normally used in AdTech and the like, deployed on clusters of hundreds of machines, holding up to petabytes of data. But ClickHouse is straightforward to use on a smaller scale as well -- you laptop will do, and don't be surprised if you are able to process several gigabytes of data per second on this hardware. There is another kind of small-scale, though pretty powerful, platforms, that is ubiquitous now -- smartphones. The conclusion inevitably follows: you must be able to run ClickHouse on your smartphone as well. It's also that I can't help but chuckle at the idea of setting up a high performance mobile OLAP cluster using a dozen of phones. Or also at the idea of seeing the nostalgic `Segmentation fault (core dumped)` on the lovely OLED screen, but I digress. Let's get it going. -### First cheap attempt +## First cheap attempt I heard somewhere that Android uses the Linux kernel, and I can already run familiar UNIX-like shell and tools using [Termux](https://termux.com/). And ClickHouse already supports ARM platform and even publishes a binary built for 64-bit ARM. This binary also doesn't have a lot of dependencies -- only a pretty old version of `glibc`. Maybe I can just download a ClickHouse binary from CI to the phone and run it? @@ -22,7 +22,7 @@ Turns out it's not that simple. * But it only gets worse. Now it complains about TLS section offset being wrong. After reading some mail archives where I could barely understand a word, I concluded that Android uses some different layout of memory for the section of the executable that holds thread-local variables, and `clang` from Android toolchain is patched to account for this. After that, I had to accept I won't be able to use familiar tools, and reluctantly turned to the Android toolchain. -### Using the Android toolchain +## Using the Android toolchain Surprisingly, it's rather simple to set up. Our build system uses CMake and already supports cross-compilation -- we have CI configurations that cross-compile for Mac, AArch64 Linux and FreeBSD. Android NDK also has integration with CMake and a [manual](https://developer.android.com/ndk/guides/cmake) on how to set it up. Download the Android NDK, add some flags to your `cmake` invocation: `DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r21d/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28`, and you're done. It (almost) builds. What obstacles do we have this time? @@ -32,7 +32,7 @@ Surprisingly, it's rather simple to set up. Our build system uses CMake and alre * `std::filesystem` is still not fully supported in NDK r21 -- the support went into r22 that is scheduled for Q3 2020, but I want it now... Good that we bundle our own forks of `libcxx` and `libcxxabi` to reduce dependencies, and they are fresh enough to fully support C++20. After enabling them, everything works. * Weird twenty-screens errors in `std::map` or something like that, that are also resolved by using our `libcxx`. -### On the device +## On the device At last, we have a binary we can actually run. Copy it to the phone, `chmod +x`, `./clickhouse server --config-path db/config.xml`, run some queries, it works! @@ -65,7 +65,7 @@ Thread 60 "ConfigReloader" received signal SIGSEGV, Segmentation fault. What is this function, and why do we need it? In this particular stack trace, we're out of memory, and about to throw an exception for that. `unw_backtrace` is called to produce a backtrace for the exception message. But there is another interesting context where we call it. Believe it or not, ClickHouse has a built-in `perf`-like sampling profiler that can save stack traces for CPU time and real time, and also memory allocations. The data is saved into a `system.trace_log` table, so you can build flame graphs for what your query was doing as simple as piping output of an SQL query into `flamegraph.pl`. This is an interesting feature, but what is relevant now is that it sends signals to all threads of the server to interrupt them at some random time and save their current backtraces, using the same `unw_backtrace` function that we know to segfault. We expect query profiler to be used in production environment, so it is enabled by default. After disabling it, we have a functioning ClickHouse server running on Android. -### Is your phone good enough? +## Is your phone good enough? There is a beaten genre of using data sets and queries of a varying degree of syntheticity to prove that a particular DBMS you work on has performance superior to other, less advanced, DBMSes. We've moved past that, and instead use the DBMS we love as a benchmark of hardware. For this benchmark we use a small 100M rows obfuscated data set from Yandex.Metrica, about 12 GB compressed, and some queries representative of Metrica dashboards. There is [this page](https://clickhouse.tech/benchmark/hardware/) with crowdsourced results for various cloud and traditional servers and even some laptops, but how do the phones compare? Let's find out. Following [the manual](https://clickhouse.tech/docs/en/operations/performance-test/) to download the necessary data to the phone and run the benchmark was pretty straightforward. One problem was that some queries can't run because they use too much memory and the server gets killed by Android, so I had to script around that. Also I'm not sure how to reset a file system cache on Android, so the 'cold run' data is not correct. The results look pretty good: @@ -73,7 +73,7 @@ There is a beaten genre of using data sets and queries of a varying degree of sy My phone is Google Pixel 3a, and it is only 5 times slower on average than my Dell XPS 15 work laptop. The queries where the data doesn't fit into memory and has to go to disk (the flash, I mean) are noticeably slower, up to 20 times, but mostly they don't complete because the server gets killed -- it only has about 3 GB of memory available. Overall I think the results look pretty good for the phone. High-end models should be even more performant, reaching performance comparable to some smaller laptops. -### Conclusion +## Conclusion This was a rather enjoyable exercise. Running a server on your phone is a nice way to give a demo, so we should probably publish a Termux package for ClickHouse. For this, we have to debug and fix the `unw_backtrace` segfault (I have my fingers crossed that it will be gone after adding `-fno-omit-frame-pointer`), and also fix some quirks that are just commented out for now. Most of the changes required for the Android build are already merged into our master branch. From 5883490268e68b465faecc91f3feffe57bc7d7ce Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 16 Jul 2020 16:45:26 +0300 Subject: [PATCH 135/143] Update pixel-bencmhark.md --- website/blog/en/2020/pixel-bencmhark.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/blog/en/2020/pixel-bencmhark.md b/website/blog/en/2020/pixel-bencmhark.md index 70e93be1226..32b21243462 100644 --- a/website/blog/en/2020/pixel-bencmhark.md +++ b/website/blog/en/2020/pixel-bencmhark.md @@ -28,8 +28,8 @@ Surprisingly, it's rather simple to set up. Our build system uses CMake and alre * Our `glibc` compatibility layer has a lot of compilation errors. It borrows `musl` code to provide functions that are absent from older versions of `glibc`, so that we can run the same binary on a wide range of distros. Being heavily dependent on system headers, it runs into all kinds of differences between Linux and Android, such as the limited scope of `pthread` support or just subtly different API variants. Thankfully we're building for a particular version of Android, so we can just disable this and use all needed functions straight from the system `libc`. * Some third-party libraries and our CMake files broken in various unimaginative ways. Just disable everything we can and fix everything we can't. -* Some of our code uses `#if defined(__linux__)` to check for Linux platform -- this doesn't always work, because Android also exports `__linux__` but there are some API differences. -* `std::filesystem` is still not fully supported in NDK r21 -- the support went into r22 that is scheduled for Q3 2020, but I want it now... Good that we bundle our own forks of `libcxx` and `libcxxabi` to reduce dependencies, and they are fresh enough to fully support C++20. After enabling them, everything works. +* Some of our code uses `#if defined(__linux__)` to check for Linux platform. This doesn't always work, because Android also exports `__linux__` but there are some API differences. +* `std::filesystem` is still not fully supported in NDK r21. The support went into r22 that is scheduled for Q3 2020, but I want it right now... Good that we bundle our own forks of `libcxx` and `libcxxabi` to reduce dependencies, and they are fresh enough to fully support C++20. After enabling them, everything works. * Weird twenty-screens errors in `std::map` or something like that, that are also resolved by using our `libcxx`. ## On the device @@ -67,7 +67,7 @@ What is this function, and why do we need it? In this particular stack trace, we ## Is your phone good enough? -There is a beaten genre of using data sets and queries of a varying degree of syntheticity to prove that a particular DBMS you work on has performance superior to other, less advanced, DBMSes. We've moved past that, and instead use the DBMS we love as a benchmark of hardware. For this benchmark we use a small 100M rows obfuscated data set from Yandex.Metrica, about 12 GB compressed, and some queries representative of Metrica dashboards. There is [this page](https://clickhouse.tech/benchmark/hardware/) with crowdsourced results for various cloud and traditional servers and even some laptops, but how do the phones compare? Let's find out. Following [the manual](https://clickhouse.tech/docs/en/operations/performance-test/) to download the necessary data to the phone and run the benchmark was pretty straightforward. One problem was that some queries can't run because they use too much memory and the server gets killed by Android, so I had to script around that. Also I'm not sure how to reset a file system cache on Android, so the 'cold run' data is not correct. The results look pretty good: +There is a beaten genre of using data sets and queries of a varying degree of syntheticity to prove that a particular DBMS you work on has performance superior to other, less advanced, DBMSes. We've moved past that, and instead use the DBMS we love as a benchmark of hardware. For this benchmark we use a small 100M rows obfuscated data set from Yandex.Metrica, about 12 GB compressed, and some queries representative of Metrica dashboards. There is [this page](https://clickhouse.tech/benchmark/hardware/) with crowdsourced results for various cloud and traditional servers and even some laptops, but how do the phones compare? Let's find out. Following [the manual](https://clickhouse.tech/docs/en/operations/performance-test/) to download the necessary data to the phone and run the benchmark was pretty straightforward. One problem was that some queries can't run because they use too much memory and the server gets killed by Android, so I had to script around that. Also, I'm not sure how to reset a file system cache on Android, so the 'cold run' data is not correct. The results look pretty good: From d2a327048e7aa841cf9eeef6f28c35d7d45c297d Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 16 Jul 2020 16:56:06 +0300 Subject: [PATCH 136/143] Update pixel-bencmhark.md --- website/blog/en/2020/pixel-bencmhark.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/blog/en/2020/pixel-bencmhark.md b/website/blog/en/2020/pixel-bencmhark.md index 32b21243462..c5ea6143c0c 100644 --- a/website/blog/en/2020/pixel-bencmhark.md +++ b/website/blog/en/2020/pixel-bencmhark.md @@ -16,9 +16,9 @@ I heard somewhere that Android uses the Linux kernel, and I can already run fami Turns out it's not that simple. -* First thing we'll see after trying to run is a cryptic message `./clickhouse: file is not found`. But it's right there! `strace` helps: what cannot be found is `/lib64/ld-linux-x86-64.so.2`, a linker specified in the ClickHouse binary. The linker in this case is a system program that initially loads the application binary and its dependencies before passing control to the application. Android uses a different linker located by another path, this is why we get the error. This problem can be overcome if we call the linker explicitly, e.g. `/system/bin/linker64 $(readlink -f ./clickhouse)`. +* The first thing we'll see after trying to run is a cryptic message: `./clickhouse: file is not found`. But it's right there! `strace` helps: what cannot be found is `/lib64/ld-linux-x86-64.so.2`, a linker specified in the ClickHouse binary. The linker, in this case, is a system program that initially loads the application binary and its dependencies before passing control to the application. Android uses a different linker located by another path, this is why we get the error. This problem can be overcome if we call the linker explicitly, e.g. `/system/bin/linker64 $(readlink -f ./clickhouse)`. -* Immediately we encounter another problem -- the linker complains that the binary has a wrong type `ET_EXEC`. What does this mean? Android binaries must support dynamic relocation, so that they can be loaded at any address, probably for ASLR purposes. ClickHouse binaries do not normally use position-independent code, because we have measured that it gives a small performance penalty of about 1%. After tweaking compilation and linking flags to include `-fPIC` as much as possible, and battling some really weird linker errors, we finally arrive at a relocatable binary that has a correct type `ET_DYN`. +* Immediately we encounter another problem: the linker complains that the binary has a wrong type `ET_EXEC`. What does this mean? Android binaries must support dynamic relocation, so that they can be loaded at any address, probably for ASLR purposes. ClickHouse binaries do not normally use position-independent code, because we have measured that it gives a small performance penalty of about 1%. After tweaking compilation and linking flags to include `-fPIC` as much as possible, and battling some really weird linker errors, we finally arrive at a relocatable binary that has a correct type `ET_DYN`. * But it only gets worse. Now it complains about TLS section offset being wrong. After reading some mail archives where I could barely understand a word, I concluded that Android uses some different layout of memory for the section of the executable that holds thread-local variables, and `clang` from Android toolchain is patched to account for this. After that, I had to accept I won't be able to use familiar tools, and reluctantly turned to the Android toolchain. @@ -38,7 +38,7 @@ At last, we have a binary we can actually run. Copy it to the phone, `chmod +x` -Feels soo good to see my favorite message. +Feels so good to see my favorite message. It's a full-fledged development environment here in Termux, let's install `gdb` and attach it to see where the segfault happens. Run `gdb clickhouse --ex run '--config-path ....'`, wait for it to lauch for a minute, only to see how Android kills Termux becase it is out of memory. Are 4 GB of RAM not enough, after all? Looking at the `clickhouse` binary, its size is a whoppping 1.1 GB. The major part of the bloat is due to the fact that some of our computational code is heavily specialized for particular data types (mostly via C++ templates), and also the fact that we build and link a lot of third-party libraries statically. A non-essential part of the binary is debug symbols, which help to produce good stack traces in error messages. We can remove them with `strip -s ./clickhouse` right here on the phone, and after that, the size becomes more manageable, about 400 MB. Finally we can run `gdb` and see that the segfault is somewhere in `unw_backtrace`: From dcf6cdb91e42e53a13db22c8c9ba6a2459c56613 Mon Sep 17 00:00:00 2001 From: Ivan Blinkov Date: Thu, 16 Jul 2020 18:41:05 +0300 Subject: [PATCH 137/143] Update deploy-to-test.sh --- docs/tools/deploy-to-test.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/tools/deploy-to-test.sh b/docs/tools/deploy-to-test.sh index a7fc98bb620..44e7687c905 100755 --- a/docs/tools/deploy-to-test.sh +++ b/docs/tools/deploy-to-test.sh @@ -6,7 +6,9 @@ # Before first use of this script: # 1) Set up building documentation according to https://github.com/ClickHouse/ClickHouse/tree/master/docs/tools#use-buildpy-use-build-py # 2) Create https://github.com/GIT_USER/clickhouse.github.io repo (replace GIT_USER with your GitHub login) -# 3) Send email on address from https://clickhouse.tech/#contacts asking to create GIT_USER-test.clickhouse.tech domain +# 3) Enable GitHub Pages in settings of this repo +# 4) Add file named CNAME in root of this repo with "GIT_USER-test.clickhouse.tech" content (without quotes) +# 5) Send email on address from https://clickhouse.tech/#contacts asking to create GIT_USER-test.clickhouse.tech domain # set -ex From b793f97c86b09ff6ef78ded42967c4daf95653cb Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Thu, 16 Jul 2020 19:06:33 +0300 Subject: [PATCH 138/143] add 'em dashes --- website/blog/en/2020/pixel-bencmhark.md | 14 ++-- website/blog/en/2020/pixel-bencmhark.md.orig | 85 ++++++++++++++++++++ 2 files changed, 92 insertions(+), 7 deletions(-) create mode 100644 website/blog/en/2020/pixel-bencmhark.md.orig diff --git a/website/blog/en/2020/pixel-bencmhark.md b/website/blog/en/2020/pixel-bencmhark.md index c5ea6143c0c..bcb823969ee 100644 --- a/website/blog/en/2020/pixel-bencmhark.md +++ b/website/blog/en/2020/pixel-bencmhark.md @@ -8,11 +8,11 @@ tags: ['Android', 'benchmark', 'experiment'] # Running ClickHouse on an Android phone -This is a brief description of my experiments with building ClickHouse on Android. If this is your first time hearing about ClickHouse, it is a suriprisingly fast columnar SQL DBMS for real-time reporting. It's normally used in AdTech and the like, deployed on clusters of hundreds of machines, holding up to petabytes of data. But ClickHouse is straightforward to use on a smaller scale as well -- you laptop will do, and don't be surprised if you are able to process several gigabytes of data per second on this hardware. There is another kind of small-scale, though pretty powerful, platforms, that is ubiquitous now -- smartphones. The conclusion inevitably follows: you must be able to run ClickHouse on your smartphone as well. It's also that I can't help but chuckle at the idea of setting up a high performance mobile OLAP cluster using a dozen of phones. Or also at the idea of seeing the nostalgic `Segmentation fault (core dumped)` on the lovely OLED screen, but I digress. Let's get it going. +This is a brief description of my experiments with building ClickHouse on Android. If this is your first time hearing about ClickHouse, it is a suriprisingly fast columnar SQL DBMS for real-time reporting. It's normally used in AdTech and the like, deployed on clusters of hundreds of machines, holding up to petabytes of data. But ClickHouse is straightforward to use on a smaller scale as well — you laptop will do, and don't be surprised if you are able to process several gigabytes of data per second on this hardware. There is another kind of small-scale, though pretty powerful, platforms, that is ubiquitous now — smartphones. The conclusion inevitably follows: you must be able to run ClickHouse on your smartphone as well. It's also that I can't help but chuckle at the idea of setting up a high performance mobile OLAP cluster using a dozen of phones. Or also at the idea of seeing the nostalgic `Segmentation fault (core dumped)` on the lovely OLED screen, but I digress. Let's get it going. ## First cheap attempt -I heard somewhere that Android uses the Linux kernel, and I can already run familiar UNIX-like shell and tools using [Termux](https://termux.com/). And ClickHouse already supports ARM platform and even publishes a binary built for 64-bit ARM. This binary also doesn't have a lot of dependencies -- only a pretty old version of `glibc`. Maybe I can just download a ClickHouse binary from CI to the phone and run it? +I heard somewhere that Android uses the Linux kernel, and I can already run familiar UNIX-like shell and tools using [Termux](https://termux.com/). And ClickHouse already supports ARM platform and even publishes a binary built for 64-bit ARM. This binary also doesn't have a lot of dependencies — only a pretty old version of `glibc`. Maybe I can just download a ClickHouse binary from CI to the phone and run it? Turns out it's not that simple. @@ -24,10 +24,10 @@ Turns out it's not that simple. ## Using the Android toolchain -Surprisingly, it's rather simple to set up. Our build system uses CMake and already supports cross-compilation -- we have CI configurations that cross-compile for Mac, AArch64 Linux and FreeBSD. Android NDK also has integration with CMake and a [manual](https://developer.android.com/ndk/guides/cmake) on how to set it up. Download the Android NDK, add some flags to your `cmake` invocation: `DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r21d/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28`, and you're done. It (almost) builds. What obstacles do we have this time? +Surprisingly, it's rather simple to set up. Our build system uses CMake and already supports cross-compilation — we have CI configurations that cross-compile for Mac, AArch64 Linux and FreeBSD. Android NDK also has integration with CMake and a [manual](https://developer.android.com/ndk/guides/cmake) on how to set it up. Download the Android NDK, add some flags to your `cmake` invocation: `DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r21d/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28`, and you're done. It (almost) builds. What obstacles do we have this time? * Our `glibc` compatibility layer has a lot of compilation errors. It borrows `musl` code to provide functions that are absent from older versions of `glibc`, so that we can run the same binary on a wide range of distros. Being heavily dependent on system headers, it runs into all kinds of differences between Linux and Android, such as the limited scope of `pthread` support or just subtly different API variants. Thankfully we're building for a particular version of Android, so we can just disable this and use all needed functions straight from the system `libc`. -* Some third-party libraries and our CMake files broken in various unimaginative ways. Just disable everything we can and fix everything we can't. +* Some third-party libraries and our CMake files are broken in various unimaginative ways. Just disable everything we can and fix everything we can't. * Some of our code uses `#if defined(__linux__)` to check for Linux platform. This doesn't always work, because Android also exports `__linux__` but there are some API differences. * `std::filesystem` is still not fully supported in NDK r21. The support went into r22 that is scheduled for Q3 2020, but I want it right now... Good that we bundle our own forks of `libcxx` and `libcxxabi` to reduce dependencies, and they are fresh enough to fully support C++20. After enabling them, everything works. * Weird twenty-screens errors in `std::map` or something like that, that are also resolved by using our `libcxx`. @@ -71,15 +71,15 @@ There is a beaten genre of using data sets and queries of a varying degree of sy -My phone is Google Pixel 3a, and it is only 5 times slower on average than my Dell XPS 15 work laptop. The queries where the data doesn't fit into memory and has to go to disk (the flash, I mean) are noticeably slower, up to 20 times, but mostly they don't complete because the server gets killed -- it only has about 3 GB of memory available. Overall I think the results look pretty good for the phone. High-end models should be even more performant, reaching performance comparable to some smaller laptops. +My phone is Google Pixel 3a, and it is only 5 times slower on average than my Dell XPS 15 work laptop. The queries where the data doesn't fit into memory and has to go to disk (the flash, I mean) are noticeably slower, up to 20 times, but mostly they don't complete because the server gets killed — it only has about 3 GB of memory available. Overall I think the results look pretty good for the phone. High-end models should be even more performant, reaching performance comparable to some smaller laptops. ## Conclusion This was a rather enjoyable exercise. Running a server on your phone is a nice way to give a demo, so we should probably publish a Termux package for ClickHouse. For this, we have to debug and fix the `unw_backtrace` segfault (I have my fingers crossed that it will be gone after adding `-fno-omit-frame-pointer`), and also fix some quirks that are just commented out for now. Most of the changes required for the Android build are already merged into our master branch. -Building for Android turned out to be relatively simple -- all these experiments and writing took me about four days, and it was the first time I ever did any Android-related programming. The NDK was simple to use, and our code was cross-platform enough so I only had to make minor modifications. If we didn't routinely build for AArch64 and had a hard dependency on SSE 4.2 or something, it would have been a different story. +Building for Android turned out to be relatively simple — all these experiments and writing took me about four days, and it was the first time I ever did any Android-related programming. The NDK was simple to use, and our code was cross-platform enough so I only had to make minor modifications. If we didn't routinely build for AArch64 and had a hard dependency on SSE 4.2 or something, it would have been a different story. -But the most important takeout is that now you don't have to obsess over choosing a new phone -- just benchmark it with ClickHouse. +But the most important takeout is that now you don't have to obsess over choosing a new phone — just benchmark it with ClickHouse. _2020-07-16 [Alexander Kuzmenkov](https://github.com/akuzm)_ diff --git a/website/blog/en/2020/pixel-bencmhark.md.orig b/website/blog/en/2020/pixel-bencmhark.md.orig new file mode 100644 index 00000000000..c5ea6143c0c --- /dev/null +++ b/website/blog/en/2020/pixel-bencmhark.md.orig @@ -0,0 +1,85 @@ +--- +title: 'Running ClickHouse on an Android phone' +image: 'pixel-benchmark/main.jpg' +date: '2020-07-16' +author: '[Alexander Kuzmenkov](https://github.com/akuzm)' +tags: ['Android', 'benchmark', 'experiment'] +--- + +# Running ClickHouse on an Android phone + +This is a brief description of my experiments with building ClickHouse on Android. If this is your first time hearing about ClickHouse, it is a suriprisingly fast columnar SQL DBMS for real-time reporting. It's normally used in AdTech and the like, deployed on clusters of hundreds of machines, holding up to petabytes of data. But ClickHouse is straightforward to use on a smaller scale as well -- you laptop will do, and don't be surprised if you are able to process several gigabytes of data per second on this hardware. There is another kind of small-scale, though pretty powerful, platforms, that is ubiquitous now -- smartphones. The conclusion inevitably follows: you must be able to run ClickHouse on your smartphone as well. It's also that I can't help but chuckle at the idea of setting up a high performance mobile OLAP cluster using a dozen of phones. Or also at the idea of seeing the nostalgic `Segmentation fault (core dumped)` on the lovely OLED screen, but I digress. Let's get it going. + +## First cheap attempt + +I heard somewhere that Android uses the Linux kernel, and I can already run familiar UNIX-like shell and tools using [Termux](https://termux.com/). And ClickHouse already supports ARM platform and even publishes a binary built for 64-bit ARM. This binary also doesn't have a lot of dependencies -- only a pretty old version of `glibc`. Maybe I can just download a ClickHouse binary from CI to the phone and run it? + +Turns out it's not that simple. + +* The first thing we'll see after trying to run is a cryptic message: `./clickhouse: file is not found`. But it's right there! `strace` helps: what cannot be found is `/lib64/ld-linux-x86-64.so.2`, a linker specified in the ClickHouse binary. The linker, in this case, is a system program that initially loads the application binary and its dependencies before passing control to the application. Android uses a different linker located by another path, this is why we get the error. This problem can be overcome if we call the linker explicitly, e.g. `/system/bin/linker64 $(readlink -f ./clickhouse)`. + +* Immediately we encounter another problem: the linker complains that the binary has a wrong type `ET_EXEC`. What does this mean? Android binaries must support dynamic relocation, so that they can be loaded at any address, probably for ASLR purposes. ClickHouse binaries do not normally use position-independent code, because we have measured that it gives a small performance penalty of about 1%. After tweaking compilation and linking flags to include `-fPIC` as much as possible, and battling some really weird linker errors, we finally arrive at a relocatable binary that has a correct type `ET_DYN`. + +* But it only gets worse. Now it complains about TLS section offset being wrong. After reading some mail archives where I could barely understand a word, I concluded that Android uses some different layout of memory for the section of the executable that holds thread-local variables, and `clang` from Android toolchain is patched to account for this. After that, I had to accept I won't be able to use familiar tools, and reluctantly turned to the Android toolchain. + +## Using the Android toolchain + +Surprisingly, it's rather simple to set up. Our build system uses CMake and already supports cross-compilation -- we have CI configurations that cross-compile for Mac, AArch64 Linux and FreeBSD. Android NDK also has integration with CMake and a [manual](https://developer.android.com/ndk/guides/cmake) on how to set it up. Download the Android NDK, add some flags to your `cmake` invocation: `DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r21d/build/cmake/android.toolchain.cmake -DANDROID_ABI=arm64-v8a -DANDROID_PLATFORM=28`, and you're done. It (almost) builds. What obstacles do we have this time? + +* Our `glibc` compatibility layer has a lot of compilation errors. It borrows `musl` code to provide functions that are absent from older versions of `glibc`, so that we can run the same binary on a wide range of distros. Being heavily dependent on system headers, it runs into all kinds of differences between Linux and Android, such as the limited scope of `pthread` support or just subtly different API variants. Thankfully we're building for a particular version of Android, so we can just disable this and use all needed functions straight from the system `libc`. +* Some third-party libraries and our CMake files broken in various unimaginative ways. Just disable everything we can and fix everything we can't. +* Some of our code uses `#if defined(__linux__)` to check for Linux platform. This doesn't always work, because Android also exports `__linux__` but there are some API differences. +* `std::filesystem` is still not fully supported in NDK r21. The support went into r22 that is scheduled for Q3 2020, but I want it right now... Good that we bundle our own forks of `libcxx` and `libcxxabi` to reduce dependencies, and they are fresh enough to fully support C++20. After enabling them, everything works. +* Weird twenty-screens errors in `std::map` or something like that, that are also resolved by using our `libcxx`. + +## On the device + +At last, we have a binary we can actually run. Copy it to the phone, `chmod +x`, `./clickhouse server --config-path db/config.xml`, run some queries, it works! + + + +Feels so good to see my favorite message. + +It's a full-fledged development environment here in Termux, let's install `gdb` and attach it to see where the segfault happens. Run `gdb clickhouse --ex run '--config-path ....'`, wait for it to lauch for a minute, only to see how Android kills Termux becase it is out of memory. Are 4 GB of RAM not enough, after all? Looking at the `clickhouse` binary, its size is a whoppping 1.1 GB. The major part of the bloat is due to the fact that some of our computational code is heavily specialized for particular data types (mostly via C++ templates), and also the fact that we build and link a lot of third-party libraries statically. A non-essential part of the binary is debug symbols, which help to produce good stack traces in error messages. We can remove them with `strip -s ./clickhouse` right here on the phone, and after that, the size becomes more manageable, about 400 MB. Finally we can run `gdb` and see that the segfault is somewhere in `unw_backtrace`: + +``` +Thread 60 "ConfigReloader" received signal SIGSEGV, Segmentation fault. +[Switching to LWP 21873] +0x000000556a73f740 in ?? () + +(gdb) whe 20 +#0 0x000000556a73f740 in ?? () +#1 0x000000556a744028 in ?? () +#2 0x000000556a73e5a0 in ?? () +#3 0x000000556a73d250 in unw_init_local () +#4 0x000000556a73deb8 in unw_backtrace () +#5 0x0000005562aabb54 in StackTrace::tryCapture() () +#6 0x0000005562aabb10 in StackTrace::StackTrace() () +#7 0x0000005562a8d73c in MemoryTracker::alloc(long) () +#8 0x0000005562a8db38 in MemoryTracker::alloc(long) () +#9 0x0000005562a8e8bc in CurrentMemoryTracker::alloc(long) () +#10 0x0000005562a8b88c in operator new[](unsigned long) () +#11 0x0000005569c35f08 in Poco::XML::NamePool::NamePool(unsigned long) () +... +``` + +What is this function, and why do we need it? In this particular stack trace, we're out of memory, and about to throw an exception for that. `unw_backtrace` is called to produce a backtrace for the exception message. But there is another interesting context where we call it. Believe it or not, ClickHouse has a built-in `perf`-like sampling profiler that can save stack traces for CPU time and real time, and also memory allocations. The data is saved into a `system.trace_log` table, so you can build flame graphs for what your query was doing as simple as piping output of an SQL query into `flamegraph.pl`. This is an interesting feature, but what is relevant now is that it sends signals to all threads of the server to interrupt them at some random time and save their current backtraces, using the same `unw_backtrace` function that we know to segfault. We expect query profiler to be used in production environment, so it is enabled by default. After disabling it, we have a functioning ClickHouse server running on Android. + +## Is your phone good enough? + +There is a beaten genre of using data sets and queries of a varying degree of syntheticity to prove that a particular DBMS you work on has performance superior to other, less advanced, DBMSes. We've moved past that, and instead use the DBMS we love as a benchmark of hardware. For this benchmark we use a small 100M rows obfuscated data set from Yandex.Metrica, about 12 GB compressed, and some queries representative of Metrica dashboards. There is [this page](https://clickhouse.tech/benchmark/hardware/) with crowdsourced results for various cloud and traditional servers and even some laptops, but how do the phones compare? Let's find out. Following [the manual](https://clickhouse.tech/docs/en/operations/performance-test/) to download the necessary data to the phone and run the benchmark was pretty straightforward. One problem was that some queries can't run because they use too much memory and the server gets killed by Android, so I had to script around that. Also, I'm not sure how to reset a file system cache on Android, so the 'cold run' data is not correct. The results look pretty good: + + + +My phone is Google Pixel 3a, and it is only 5 times slower on average than my Dell XPS 15 work laptop. The queries where the data doesn't fit into memory and has to go to disk (the flash, I mean) are noticeably slower, up to 20 times, but mostly they don't complete because the server gets killed -- it only has about 3 GB of memory available. Overall I think the results look pretty good for the phone. High-end models should be even more performant, reaching performance comparable to some smaller laptops. + +## Conclusion + +This was a rather enjoyable exercise. Running a server on your phone is a nice way to give a demo, so we should probably publish a Termux package for ClickHouse. For this, we have to debug and fix the `unw_backtrace` segfault (I have my fingers crossed that it will be gone after adding `-fno-omit-frame-pointer`), and also fix some quirks that are just commented out for now. Most of the changes required for the Android build are already merged into our master branch. + +Building for Android turned out to be relatively simple -- all these experiments and writing took me about four days, and it was the first time I ever did any Android-related programming. The NDK was simple to use, and our code was cross-platform enough so I only had to make minor modifications. If we didn't routinely build for AArch64 and had a hard dependency on SSE 4.2 or something, it would have been a different story. + +But the most important takeout is that now you don't have to obsess over choosing a new phone -- just benchmark it with ClickHouse. + + +_2020-07-16 [Alexander Kuzmenkov](https://github.com/akuzm)_ From abe45b76cded8c29ddbf53144fde2982310ef1ca Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Thu, 16 Jul 2020 19:07:15 +0300 Subject: [PATCH 139/143] rename file --- website/blog/en/2020/{pixel-bencmhark.md => pixel-benchmark.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename website/blog/en/2020/{pixel-bencmhark.md => pixel-benchmark.md} (100%) diff --git a/website/blog/en/2020/pixel-bencmhark.md b/website/blog/en/2020/pixel-benchmark.md similarity index 100% rename from website/blog/en/2020/pixel-bencmhark.md rename to website/blog/en/2020/pixel-benchmark.md From 782f2179ce4ad0b9a9c898a5f32557555b59e4d0 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 16 Jul 2020 19:42:05 +0300 Subject: [PATCH 140/143] Update pixel-benchmark.md --- website/blog/en/2020/pixel-benchmark.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/blog/en/2020/pixel-benchmark.md b/website/blog/en/2020/pixel-benchmark.md index bcb823969ee..d4ed3a86b59 100644 --- a/website/blog/en/2020/pixel-benchmark.md +++ b/website/blog/en/2020/pixel-benchmark.md @@ -1,6 +1,6 @@ --- title: 'Running ClickHouse on an Android phone' -image: 'pixel-benchmark/main.jpg' +image: 'https://blog-images.clickhouse.tech/en/2020/pixel-benchmark/main.jpg' date: '2020-07-16' author: '[Alexander Kuzmenkov](https://github.com/akuzm)' tags: ['Android', 'benchmark', 'experiment'] @@ -36,7 +36,7 @@ Surprisingly, it's rather simple to set up. Our build system uses CMake and alre At last, we have a binary we can actually run. Copy it to the phone, `chmod +x`, `./clickhouse server --config-path db/config.xml`, run some queries, it works! - + Feels so good to see my favorite message. @@ -69,7 +69,7 @@ What is this function, and why do we need it? In this particular stack trace, we There is a beaten genre of using data sets and queries of a varying degree of syntheticity to prove that a particular DBMS you work on has performance superior to other, less advanced, DBMSes. We've moved past that, and instead use the DBMS we love as a benchmark of hardware. For this benchmark we use a small 100M rows obfuscated data set from Yandex.Metrica, about 12 GB compressed, and some queries representative of Metrica dashboards. There is [this page](https://clickhouse.tech/benchmark/hardware/) with crowdsourced results for various cloud and traditional servers and even some laptops, but how do the phones compare? Let's find out. Following [the manual](https://clickhouse.tech/docs/en/operations/performance-test/) to download the necessary data to the phone and run the benchmark was pretty straightforward. One problem was that some queries can't run because they use too much memory and the server gets killed by Android, so I had to script around that. Also, I'm not sure how to reset a file system cache on Android, so the 'cold run' data is not correct. The results look pretty good: - + My phone is Google Pixel 3a, and it is only 5 times slower on average than my Dell XPS 15 work laptop. The queries where the data doesn't fit into memory and has to go to disk (the flash, I mean) are noticeably slower, up to 20 times, but mostly they don't complete because the server gets killed — it only has about 3 GB of memory available. Overall I think the results look pretty good for the phone. High-end models should be even more performant, reaching performance comparable to some smaller laptops. From dd2adad0ce1e982d114c035f58cfbb05082541ff Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Thu, 16 Jul 2020 20:04:55 +0300 Subject: [PATCH 141/143] Update pixel-benchmark.md --- website/blog/en/2020/pixel-benchmark.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/blog/en/2020/pixel-benchmark.md b/website/blog/en/2020/pixel-benchmark.md index d4ed3a86b59..9cf83edffd6 100644 --- a/website/blog/en/2020/pixel-benchmark.md +++ b/website/blog/en/2020/pixel-benchmark.md @@ -16,7 +16,7 @@ I heard somewhere that Android uses the Linux kernel, and I can already run fami Turns out it's not that simple. -* The first thing we'll see after trying to run is a cryptic message: `./clickhouse: file is not found`. But it's right there! `strace` helps: what cannot be found is `/lib64/ld-linux-x86-64.so.2`, a linker specified in the ClickHouse binary. The linker, in this case, is a system program that initially loads the application binary and its dependencies before passing control to the application. Android uses a different linker located by another path, this is why we get the error. This problem can be overcome if we call the linker explicitly, e.g. `/system/bin/linker64 $(readlink -f ./clickhouse)`. +* The first thing we'll see after trying to run is an absurd error message: `./clickhouse: file is not found`. But it's right there! `strace` helps: what cannot be found is `/lib64/ld-linux-x86-64.so.2`, a linker specified in the ClickHouse binary. The linker, in this case, is a system program that initially loads the application binary and its dependencies before passing control to the application. Android uses a different linker located by another path, this is why we get the error. This problem can be overcome if we call the linker explicitly, e.g. `/system/bin/linker64 $(readlink -f ./clickhouse)`. * Immediately we encounter another problem: the linker complains that the binary has a wrong type `ET_EXEC`. What does this mean? Android binaries must support dynamic relocation, so that they can be loaded at any address, probably for ASLR purposes. ClickHouse binaries do not normally use position-independent code, because we have measured that it gives a small performance penalty of about 1%. After tweaking compilation and linking flags to include `-fPIC` as much as possible, and battling some really weird linker errors, we finally arrive at a relocatable binary that has a correct type `ET_DYN`. From 49ca315e30b0fa77d32ff456d7ccd6b1638e1dd2 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov Date: Thu, 16 Jul 2020 20:08:14 +0300 Subject: [PATCH 142/143] remove images --- .../blog/en/2020/pixel-bencmhark/compare.png | Bin 55265 -> 0 bytes website/blog/en/2020/pixel-bencmhark/main.jpg | Bin 29411 -> 0 bytes .../blog/en/2020/pixel-bencmhark/segfault.png | Bin 471124 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 website/blog/en/2020/pixel-bencmhark/compare.png delete mode 100644 website/blog/en/2020/pixel-bencmhark/main.jpg delete mode 100644 website/blog/en/2020/pixel-bencmhark/segfault.png diff --git a/website/blog/en/2020/pixel-bencmhark/compare.png b/website/blog/en/2020/pixel-bencmhark/compare.png deleted file mode 100644 index 573d13f67a59440fde7f988974682a563c8958a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55265 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

KTq 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
t_jAnsSYS$@1Z!P;ZjrSeFgtIn2kt|4NNKJzp8G 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�(=3DkyDS!N-YL|Pwy`}T}} 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

D- zV`LCSD`!Z-3Rwa>?dq$D$M$x1(2fIZw`Qe<%w33!QO%Zvf>RhOzl8(*6%XEq)KWDD zc}2w)yPB4k79?LVy%cKIl-Aa|fxpu!??Z)NhPYwY=`a7zKM=rz_|pAOU2Xac?CHRv zXTj3@Kx^aApAQ(aS;N`;E~>?p%Ht%FOeM04Q?2f4(%_pBKHn^J)85OkdVe`>8Qp{n z@fM4qXM(@dU=b=RDhRwkfByXN;X@Qr;OISJ5hTM|f!HlBx0=vdOw5iCV>Mov&mt)* z9~88Q&!O&M-1Se@m7(Iul#vYTWEMEKv6aTLxkF`i>Oucl!rXq2qu!%&r-!d!Xh<-E zae)5I3PQw(wJms#48hwRx7{$Ic=y0dN-)`vbYP?GK>|rO!5yK8Co~5V{4#_G=2_pF zwBx&ITtt7^&=oQw4jf1h%)0_jaou}lNUwhJJFZ8~;z4H#On#HwpN-b$nyx_=EAa^L z43fP$p~QNV{_tSe-LfYJ=N{qub5}|ImoIb0p4>+#7x zFJET8Ey)OTW_7D`KP2k?gRanV(OqlH4Slf<&(=nk`^AQeR7@R}WpDyo4{gku@9`l- zdgm326fO=1EGfUM9hNPSV$n+B$F$zZph2W6J+~}U&VY8Fdlj1U5$_;-1lG5k!dO)Z z&HfY|OkE+D$U7AEMac7v9v?$(3zWWTY4QJt;99`smi`AOHc;MIydlpQLtfp5+6O8= z*#65S#-(Ce^~Ln{AJz^5+5$I|QVnSF<(PG=Z5~2=7^&Sv7=2!d%u(^q&C`Y@TJ>{a zfQ6A!{Mq0yYmx$1%=4=0{EuyI5^8D1#k&>1bTU3mOG;|j*r6sx$Y#M7&GX-d&O3f= zPwxkP*fV-Os6H`TogLEOccda-Jz{_>`%w;4!d`TKc`&vv{PEe^yxzM)vbDht1-kZ` z=XSaYAJLPoUH^GH4pc@(3bh3n}+#k za`3XXPNT&RtX;yId)7@tk=okzDTQzCpusVZBE_TF__Va)#oT3`b6APO=WWHdS{M0* zdZa+@MvEfdeH+Y#Q7VUxXJl)q|Aw{U(O$6O4BpjZ-tl8*@vaAabh=<;S4yq)b=g-n zZ%x`XP(!Zn>3^6jFSI)90&I~CqLhegu>#pkW-vdLd?>Z%9 zQcB6j`@xzF5|&N(VTxHyL13YBU zB=M-m_RsC_Hc;fQ>RfW>u78-EPnh}jHn$o=&wpUJKaI_e`?gr0E$8kHszR zr!7oQ_6tcFJD1nC6cdc64`CCmJL*6OZtDx$5N&_jq8*lt-cJ7FM(52*&(ZR3Ml$jl zEX9AP>8JKQj~0sR1)3ToNF(A#nnc}>*4f5)Eq0Rs3{J)sd5`SYDi?FALHl3b&V?_t z_40iS$HPs$@;A-&q}&!FMY3LAjYAl~?SY7LEbf`(cYQywHIOD1Ks8WJxZrBD|LwsA zu$+k9i{;gL)8~DCDIJliSuk5|OZ`mcL;%jS2}Ex$>Fa+D z#gdBS!BU)R2p{oPel6wt?MtEfR7y+pH1Uf&$EMGJw12usd+2#`6+_*#Efw)?$~c%0 zhlhWhjZMwRk+IM*U(8W6Xo@Hq8?QprxJW{c)zpu`)Il7zKqumHw+*$SjS>piG4`&t z<)l3NkLoo{#Eh;BDtd~rbB5s$Qh(gpY2Sl`gIykhjU{5ApUj@eJN~~y-)E%_7s^{Z zY=!(%f1_RH-}cvpNjRCqPHe8B4>Kj~yNLPCO@X&< zci@i2#!hXGdZMbd0JSmtX}QGU|8|A_-g(w_rJ!n7OghA^e|Ubo@HIO#b7jFfwV;Jm z6j;wb8veJKGd#{>~pe>Rz|Ag%}PtC+`zb2)Lvw5fMLtcLkS1 zKt#b5PH(Kw#$5azSp5ndZ-OeP-s?iuFMwsm^N(aDhCE!T@{APSD$kzlAbjpBPiwjQ&raHu7!eDreznk!jweF$<&`7- zyMB}u$=yKcIm&|T+*CZ6gSh4vn)QY4l0uOx=0%=)4@NLWR_3g%Tw}IUEP7D0ikQsn z

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

-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 R#F}2yeKj4`vU^q`{|$p2X|(_V diff --git a/website/blog/en/2020/pixel-bencmhark/main.jpg b/website/blog/en/2020/pixel-bencmhark/main.jpg deleted file mode 100644 index b511a28a96067c4463b49cb92e5260cd9afc2c86..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29411 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 z 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 z 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

-QvY( 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 ?ZfI zAH>5Ul8yQ=Gl3uFb!r6AWepx;1d9J2RTjy*XoZ#&Fa@BeHd0&%=^YTE_On0bWJ33R z_#SCEP_&z%z(PC%BNv!Ai~vADhAU%#;^X53Zh%Hud8D=aU@8tEaO)mM0nATB#wiuu zxApB33VFD91Jr!k8>tRe9gZ9I&xaggt-npma3*^1cAK(q?32ZqtY&;M6`wl@;Zdr! z$HZ3Dwh0d{sMcRj{T}?%Sf4G#g=BD>>PNHaMz6A~tMW(jA?n3W?V1R5JFnb_iW^b5 z6}vtMX~zwfY#og#6x~N^IC=N){YG&@1%Iuz{q8r6z&%G4Z(XCUE?t5QdeFZlTs+gqI`?q1TR@NV4<)xs78ByT5 zC70JG;`+DtzET&~fd1^ATj{6>J*^0fjMGn5EVVh6ayhCnvBf~^bkG+@ zje`oyH)nRQU)f;J{D0bXjyC>CESM|0jafD^Ht6*%Wue6@s&u ziTp*uDapkymvzIBq;V0+$;IAR%X82SOjN8XkTHVh8wko>U5h1|XfR=zS6}}+vf}pI za(9Yqf?=Y& zxI!=6uE^oswc!XArr${%zYW#t{wUCF5{5KD76T}qw>FLG&Jy*VS|$e|z(LjM2B>2< zFm!ZuV9cB`7!ek>^7}PnZ^pj)xtUpFga+6%!vJIg`4x(zdSuD_o>yd|e zwyuZnh@Ak+EoBr0ubZC@m(v2D%#NyEayag_CekCLN-K)O`FeTyyQw4Ad&<{v^Z>0%5XwY82nj3|r$2kfqCs(lm-RKv>Xf=E#5==%g-P zRWrUld1fb55cjl`?8(!k$Bu7B^G33Bq&K~a)foQ>AL@(!h-&e%R2LScskOEP2|9$H zC=oY+=oLcE%WK7~w08!C{ytV$=z#Tjd2^{uH!^(%MEo-E?YIr&-yb$oVYcl^VLxnr z-)JR(GLwQ8cvxUtz5x4!hG<%=gEUTn8ly<;LHp{ZKe!sh&n>6CXra^DGp3A<9@9sb z8LCrS?_jkXGCI?*aSIGp=i7K}eTnDKt|fxd_*``-J<_wb;W@cSaa)M=PM8`)u2v`u zbE-N04en#KrS*_flMthk)8Il4QZf8=3g2|s&V|qpedw}lYTDV6960{*U5noYJ3h_H z^Gdg%jc&y}j!FoyzX!t2IpED@ONBCkWk8-BAeuY1@_CM16QzL12n`GS;2hP_5=3nKn&r%5t>1=dj!|{tT5{42cv&FS~^n>++|>RDw!#SGReM!pF4Z(8vp7 zNnt!YhLS`Cy|M$x8Z{I5@9gSTmT5MzsRaB#sQ4O`>x;sh@9oF282%D$y7=2*zYeQd zcd9RM?^nK_W#wWCU{A(BFM1(}`APGw`>jM_1nNf#A9BYo^iP@$S5>ad6YnF7&Qy@Y z#Kc9|F2sI}o7P&F(bFo1Vk%3&%F~}KUA^N5t`im(QLn~RMev0{V<0Dc1dNUJ=n5=5 zc9u+RtbE?p>oiGN<_;ik$oz1w1D!%y2eOQxQh6g^3B+V9Or@m6epH)UJ}#;$`|K)_ zcg&ASiU7aA_wP#?JeXB(r*5vV6e)`mHBVo4C4)+*v~z56 zvXl924v+2pOgbPC`{d*vgtPS;9}r_(028l6T-8GT)p%+0J#dK0vdH$&j*ox3IynNt zC{zjHYI*hQz?AP*p+-FjOEG6=rnhXi-Z2-KB`T-KkK9Iu_noU~{^Zz0mu7PE?ptWj z>os^W3A>0}%6>_(_{bSkI&9fNASPkzW_7k|BSqh@6)rh8Hh=0q`e7*YbNAkgkB?

rx!*0m<4<8 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 ZT(;P>;L}UVEF Date: Thu, 16 Jul 2020 20:40:44 +0300 Subject: [PATCH 143/143] Update pixel-benchmark.md --- website/blog/en/2020/pixel-benchmark.md | 1 - 1 file changed, 1 deletion(-) diff --git a/website/blog/en/2020/pixel-benchmark.md b/website/blog/en/2020/pixel-benchmark.md index 9cf83edffd6..b9be7638c38 100644 --- a/website/blog/en/2020/pixel-benchmark.md +++ b/website/blog/en/2020/pixel-benchmark.md @@ -6,7 +6,6 @@ author: '[Alexander Kuzmenkov](https://github.com/akuzm)' tags: ['Android', 'benchmark', 'experiment'] --- -# Running ClickHouse on an Android phone This is a brief description of my experiments with building ClickHouse on Android. If this is your first time hearing about ClickHouse, it is a suriprisingly fast columnar SQL DBMS for real-time reporting. It's normally used in AdTech and the like, deployed on clusters of hundreds of machines, holding up to petabytes of data. But ClickHouse is straightforward to use on a smaller scale as well — you laptop will do, and don't be surprised if you are able to process several gigabytes of data per second on this hardware. There is another kind of small-scale, though pretty powerful, platforms, that is ubiquitous now — smartphones. The conclusion inevitably follows: you must be able to run ClickHouse on your smartphone as well. It's also that I can't help but chuckle at the idea of setting up a high performance mobile OLAP cluster using a dozen of phones. Or also at the idea of seeing the nostalgic `Segmentation fault (core dumped)` on the lovely OLED screen, but I digress. Let's get it going.