Allow to override host for client connection credentials

Introduce new `--connection` option, by default as a connection name
`--host` will be used.

And using --connection you also can specify --host and it will be
overwritten.

Follow-up for: #45715
Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
This commit is contained in:
Azat Khuzhin 2023-02-16 13:38:25 +01:00
parent 2145a29cb6
commit 2dbcfdbe15
3 changed files with 51 additions and 29 deletions

View File

@ -69,6 +69,7 @@ namespace ErrorCodes
extern const int TOO_DEEP_RECURSION;
extern const int NETWORK_ERROR;
extern const int AUTHENTICATION_FAILED;
extern const int NO_ELEMENTS_IN_CONFIG;
}
@ -134,29 +135,34 @@ void Client::parseConnectionsCredentials()
if (hosts_and_ports.size() >= 2)
return;
String host;
std::optional<UInt16> port;
std::optional<String> host;
if (hosts_and_ports.empty())
{
host = config().getString("host", "localhost");
if (config().has("port"))
port = config().getInt("port");
if (config().has("host"))
host = config().getString("host");
}
else
{
host = hosts_and_ports.front().host;
port = hosts_and_ports.front().port;
}
String connection;
if (config().has("connection"))
connection = config().getString("connection");
else
connection = host.value_or("localhost");
Strings keys;
config().keys("connections_credentials", keys);
for (const auto & connection : keys)
bool connection_found = false;
for (const auto & key : keys)
{
const String & prefix = "connections_credentials." + connection;
const String & prefix = "connections_credentials." + key;
const String & connection_name = config().getString(prefix + ".name", "");
if (connection_name != host)
if (connection_name != connection)
continue;
connection_found = true;
String connection_hostname;
if (config().has(prefix + ".hostname"))
@ -164,14 +170,9 @@ void Client::parseConnectionsCredentials()
else
connection_hostname = connection_name;
/// Set "host" unconditionally (since it is used as a "name"), while
/// other options only if they are not set yet (config.xml/cli
/// options).
config().setString("host", connection_hostname);
if (!hosts_and_ports.empty())
hosts_and_ports.front().host = connection_hostname;
if (config().has(prefix + ".port") && !port.has_value())
if (hosts_and_ports.empty())
config().setString("host", connection_hostname);
if (config().has(prefix + ".port") && hosts_and_ports.empty())
config().setInt("port", config().getInt(prefix + ".port"));
if (config().has(prefix + ".secure") && !config().has("secure"))
config().setBool("secure", config().getBool(prefix + ".secure"));
@ -189,6 +190,9 @@ void Client::parseConnectionsCredentials()
config().setString("history_file", history_file);
}
}
if (config().has("connection") && !connection_found)
throw Exception(ErrorCodes::NO_ELEMENTS_IN_CONFIG, "No such connection '{}' in connections_credentials", connection);
}
/// Make query to get all server warnings
@ -955,6 +959,7 @@ void Client::addOptions(OptionsDescription & options_description)
/// Main commandline options related to client functionality and all parameters from Settings.
options_description.main_description->add_options()
("config,c", po::value<std::string>(), "config-file path (another shorthand)")
("connection", po::value<std::string>(), "connection to use (from the client config), by default connection name is hostname")
("secure,s", "Use TLS connection")
("user,u", po::value<std::string>()->default_value("default"), "user")
/** If "--password [value]" is used but the value is omitted, the bad argument exception will be thrown.
@ -1095,6 +1100,8 @@ void Client::processOptions(const OptionsDescription & options_description,
if (options.count("config"))
config().setString("config-file", options["config"].as<std::string>());
if (options.count("connection"))
config().setString("connection", options["connection"].as<std::string>());
if (options.count("interleave-queries-file"))
interleave_queries_files = options["interleave-queries-file"].as<std::vector<std::string>>();
if (options.count("secure"))

View File

@ -1,5 +1,10 @@
connection
No such connection 'no_such_connection' in connections_credentials
hostname
Not found address of host: MySQL.
Not found address of host: test_hostname_invalid.
1
system
system
port
Connection refused (localhost:0).
9000

View File

@ -22,10 +22,15 @@ cat > $CONFIG <<EOL
<connections_credentials>
<connection>
<name>test_hostname</name>
<name>test_hostname_invalid</name>
<hostname>MySQL</hostname>
</connection>
<connection>
<name>$TEST_HOST</name>
<database>system</database>
</connection>
<connection>
<name>test_port</name>
<hostname>$TEST_HOST</hostname>
@ -65,22 +70,27 @@ cat > $CONFIG <<EOL
</clickhouse>
EOL
echo 'connection'
$CLICKHOUSE_CLIENT --config $CONFIG --connection no_such_connection -q 'select 1' |& grep -F -o "No such connection 'no_such_connection' in connections_credentials"
echo 'hostname'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_hostname -q 'select 1' |& grep -F -o 'Not found address of host: MySQL.'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_hostname_invalid -q 'select 1' |& grep -F -o 'Not found address of host: test_hostname_invalid.'
$CLICKHOUSE_CLIENT --config $CONFIG --connection test_hostname_invalid --host $TEST_HOST -q 'select 1'
$CLICKHOUSE_CLIENT --config $CONFIG -q 'select currentDatabase()'
$CLICKHOUSE_CLIENT --config $CONFIG --host $TEST_HOST -q 'select currentDatabase()'
echo 'port'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_port -q 'select tcpPort()' |& grep -F -o 'Connection refused (localhost:0).'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_port --port $TEST_PORT -q 'select tcpPort()'
$CLICKHOUSE_CLIENT --config $CONFIG --connection test_port -q 'select tcpPort()' |& grep -F -o 'Connection refused (localhost:0).'
$CLICKHOUSE_CLIENT --config $CONFIG --connection test_port --port $TEST_PORT -q 'select tcpPort()'
echo 'secure'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_secure -q 'select tcpPort()' |& grep -c -F -o -e OPENSSL_internal:WRONG_VERSION_NUMBER -e 'tcp_secure protocol is disabled because poco library was built without NetSSL support.'
$CLICKHOUSE_CLIENT --config $CONFIG --connection test_secure -q 'select tcpPort()' |& grep -c -F -o -e OPENSSL_internal:WRONG_VERSION_NUMBER -e 'tcp_secure protocol is disabled because poco library was built without NetSSL support.'
echo 'database'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_database -q 'select currentDatabase()'
$CLICKHOUSE_CLIENT --config $CONFIG --connection test_database -q 'select currentDatabase()'
echo 'user'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_user -q 'select currentUser()' |& grep -F -o 'MySQL: Authentication failed'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_user --user default -q 'select currentUser()'
$CLICKHOUSE_CLIENT --config $CONFIG --connection test_user -q 'select currentUser()' |& grep -F -o 'MySQL: Authentication failed'
$CLICKHOUSE_CLIENT --config $CONFIG --connection test_user --user default -q 'select currentUser()'
echo 'password'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_password -q 'select currentUser()' |& grep -F -o 'default: Authentication failed: password is incorrect, or there is no user with such name.'
$CLICKHOUSE_CLIENT --config $CONFIG --host test_password --password "" -q 'select currentUser()'
$CLICKHOUSE_CLIENT --config $CONFIG --connection test_password -q 'select currentUser()' |& grep -F -o 'default: Authentication failed: password is incorrect, or there is no user with such name.'
$CLICKHOUSE_CLIENT --config $CONFIG --connection test_password --password "" -q 'select currentUser()'
echo 'history_file'
$CLICKHOUSE_CLIENT --progress off --interactive --config $CONFIG --host test_history_file -q 'select 1' </dev/null |& grep -F -o 'Cannot create file: /no/such/dir/.history'
$CLICKHOUSE_CLIENT --progress off --interactive --config $CONFIG --connection test_history_file -q 'select 1' </dev/null |& grep -F -o 'Cannot create file: /no/such/dir/.history'
rm -f "${CONFIG:?}"