-
Notifications
You must be signed in to change notification settings - Fork 690
Add config node init command #14869
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add config node init command #14869
Changes from all commits
575f1bc
8d4ab14
f9a12d8
ae7ac57
17c1ff4
7d72e5c
df0e0d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#include "ydb_node_config.h" | ||
#include <util/system/fs.h> | ||
#include <util/folder/dirut.h> | ||
#include <ydb-cpp-sdk/client/config/config.h> | ||
|
||
namespace NYdb::NConsoleClient::NNodeConfig { | ||
|
||
constexpr const char* CONFIG_FILE_NAME = "config.yaml"; | ||
constexpr const char* STORAGE_CONFIG_FILE_NAME = "storage.yaml"; | ||
|
||
TCommandNodeConfig::TCommandNodeConfig() | ||
: TClientCommandTree("config", {}, "Node-wide configuration") | ||
{ | ||
AddCommand(std::make_unique<TCommandNodeConfigInit>()); | ||
} | ||
|
||
TCommandNodeConfigInit::TCommandNodeConfigInit() | ||
: TYdbCommand("init", {}, "Initialize node configuration") | ||
{ | ||
} | ||
|
||
void TCommandNodeConfigInit::PropagateFlags(const TCommandFlags& flags) { | ||
Gazizonoki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
TYdbCommand::PropagateFlags(flags); | ||
Dangerous = false; | ||
} | ||
|
||
void TCommandNodeConfigInit::Config(TConfig& config) { | ||
TYdbCommand::Config(config); | ||
config.Opts->AddLongOption('f', "from-config", "Path to the initial configuration file.") | ||
.RequiredArgument("[config.yaml]").StoreResult(&ConfigYamlPath); | ||
config.Opts->AddLongOption('d', "config-dir", "Path to the directory for storing configuration files.") | ||
.Required().RequiredArgument("[directory]").StoreResult(&ConfigDirPath); | ||
config.Opts->AddLongOption('s', "seed-node", "Endpoint of the seed node from which the configuration will be fetched.") | ||
.RequiredArgument("[HOST:PORT]").StoreResult(&SeedNodeEndpoint); | ||
config.Opts->MutuallyExclusive("from-config", "seed-node"); | ||
config.SetFreeArgsNum(0); | ||
config.AllowEmptyDatabase = true; | ||
config.AllowEmptyAddress = true; | ||
} | ||
|
||
bool TCommandNodeConfigInit::SaveConfig(const TString& config, const TString& configName, const TString& configDirPath) { | ||
try { | ||
TString tempPath = TStringBuilder() << configDirPath << "/temp_" << configName; | ||
TString configPath = TStringBuilder() << configDirPath << "/" << configName; | ||
|
||
{ | ||
TFileOutput tempFile(tempPath); | ||
tempFile << config; | ||
tempFile.Flush(); | ||
|
||
if (Chmod(tempPath.c_str(), S_IRUSR | S_IRGRP | S_IROTH) != 0) { | ||
return false; | ||
} | ||
} | ||
|
||
return NFs::Rename(tempPath, configPath); | ||
} catch (const std::exception& e) { | ||
return false; | ||
} | ||
} | ||
|
||
int TCommandNodeConfigInit::Run(TConfig& config) { | ||
MakePathIfNotExist(ConfigDirPath.c_str()); | ||
TString configYaml; | ||
|
||
if (SeedNodeEndpoint) { | ||
config.Address = SeedNodeEndpoint; | ||
auto driver = std::make_unique<NYdb::TDriver>(CreateDriver(config)); | ||
auto client = NYdb::NConfig::TConfigClient(*driver); | ||
|
||
auto result = client.FetchAllConfigs().GetValueSync(); | ||
NStatusHelpers::ThrowOnErrorOrPrintIssues(result); | ||
TString clusterConfig; | ||
TString storageConfig; | ||
for (const auto& entry : result.GetConfigs()) { | ||
std::visit([&](auto&& arg) { | ||
using T = std::decay_t<decltype(arg)>; | ||
if constexpr (std::is_same_v<T, NYdb::NConfig::TMainConfigIdentity>) { | ||
Gazizonoki marked this conversation as resolved.
Show resolved
Hide resolved
|
||
clusterConfig = entry.Config; | ||
} else if constexpr (std::is_same_v<T, NYdb::NConfig::TStorageConfigIdentity>) { | ||
storageConfig = entry.Config; | ||
} | ||
}, entry.Identity); | ||
} | ||
bool hasCluster = !clusterConfig.empty(); | ||
bool hasStorage = !storageConfig.empty(); | ||
bool clusterSaved = false; | ||
bool storageSaved = false; | ||
|
||
if (hasCluster && hasStorage) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. На мой взгляд ниже много boilerplate кода, по куче раз конфиги сохраняем. Лучше в как-то в одном месте сделать, и потом писать вывод на основе того, что пытались сохранить, что получилось сохранить. Но тут скорее на твое усмотрение и на усмотрение @pnv1 |
||
clusterSaved = SaveConfig(clusterConfig, CONFIG_FILE_NAME, ConfigDirPath); | ||
storageSaved = SaveConfig(storageConfig, STORAGE_CONFIG_FILE_NAME, ConfigDirPath); | ||
|
||
if (clusterSaved && storageSaved) { | ||
Cout << "Initialized main and storage configs in " << ConfigDirPath << "/" | ||
<< CONFIG_FILE_NAME << " and " << STORAGE_CONFIG_FILE_NAME << Endl; | ||
return EXIT_SUCCESS; | ||
} | ||
Cerr << "Failed to save configs: " | ||
<< (clusterSaved ? "" : "main config ") | ||
<< (storageSaved ? "and " : "storage config") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А что если clusterSaved = false, а storageSaved = true There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Все равно должна выдаваться ошибка. То что там теперь лежит бесполезный файл storage не должно никак повлиять, так как это файлы только для системы There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Я про текст ошибки: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Понял, поторопился) |
||
<< Endl; | ||
return EXIT_FAILURE; | ||
} | ||
|
||
if (hasCluster) { | ||
clusterSaved = SaveConfig(clusterConfig, CONFIG_FILE_NAME, ConfigDirPath); | ||
if (clusterSaved) { | ||
Cout << "Initialized config in " << ConfigDirPath << "/" << CONFIG_FILE_NAME << Endl; | ||
return EXIT_SUCCESS; | ||
} | ||
Cerr << "Failed to save config to " << ConfigDirPath << Endl; | ||
return EXIT_FAILURE; | ||
} | ||
|
||
Cerr << "No main config found" << Endl; | ||
return EXIT_FAILURE; | ||
} | ||
|
||
configYaml = TFileInput(ConfigYamlPath).ReadAll(); | ||
if (SaveConfig(configYaml, CONFIG_FILE_NAME, ConfigDirPath)){ | ||
Cout << "Initialized cluster config in " << ConfigDirPath << "/" << CONFIG_FILE_NAME << Endl; | ||
return EXIT_SUCCESS; | ||
} else { | ||
Cout << "Failed to initialize cluster config in " << ConfigDirPath << "/" << CONFIG_FILE_NAME << Endl; | ||
return EXIT_FAILURE; | ||
} | ||
|
||
} | ||
|
||
} // namespace NYdb::NConsoleClient::NNodeConfig |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#pragma once | ||
|
||
#include "ydb_command.h" | ||
|
||
namespace NYdb::NConsoleClient::NNodeConfig { | ||
|
||
class TCommandNodeConfig : public TClientCommandTree { | ||
public: | ||
TCommandNodeConfig(); | ||
}; | ||
|
||
class TCommandNodeConfigInit : public TYdbCommand { | ||
public: | ||
TCommandNodeConfigInit(); | ||
void PropagateFlags(const TCommandFlags& flags) override; | ||
void Config(TConfig& config) override; | ||
int Run(TConfig& config) override; | ||
bool SaveConfig(const TString& config, const TString& configName, const TString& configDirPath); | ||
private: | ||
TString ConfigYamlPath; | ||
TString ConfigDirPath; | ||
TString SeedNodeEndpoint; | ||
}; | ||
|
||
} // namespace NYdb::NConsoleClient::NNodeConfig |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.