blob: 350348a7c92e1e2f2a2c81d08e729bc2aff766df [file] [edit]
#include "tlbmc/configs/rate_limiter_config.h"
#include <fstream>
#include <string>
#include <string_view>
#include "absl/base/no_destructor.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h"
#include "g3/macros.h"
#include "central_config.pb.h"
#include "tlbmc/central_config/config.h"
#include "tlbmc/redfish/routes/action_managers/file_manager.h"
#include "google/protobuf/io/zero_copy_stream_impl.h"
#include "google/protobuf/text_format.h"
namespace milotic_tlbmc {
namespace {
constexpr std::string_view kDefaultConfigDir = "/var/google/tlbmc";
constexpr std::string_view kConfigFilename = "rate_limiter_config.textproto";
} // namespace
void RateLimiterConfig::LoadConfigLocked(std::string_view overlay_file_path) {
config_ = GetTlbmcConfig().redfish_rate_limiter_module();
std::ifstream overlay_file((std::string(overlay_file_path)));
if (!overlay_file.is_open()) {
LOG(INFO) << "Failed to open overlay file: " << overlay_file_path;
return;
}
::google::protobuf::io::IstreamInputStream istream_source(&overlay_file);
if (!::google::protobuf::TextFormat::Parse(&istream_source, &overlay_config_)) {
LOG(WARNING) << "Failed to parse rate limiter overlay config from "
<< overlay_file_path << ". Using config from bundle.";
return;
}
config_.MergeFrom(overlay_config_);
}
absl::Status RateLimiterConfig::SaveConfigToFile(
const RedfishRateLimiterModule& config,
std::string_view overlay_file_path) {
std::string content;
if (!::google::protobuf::TextFormat::PrintToString(config, &content)) {
return absl::InternalError("Failed to serialize configuration to string.");
}
return FileManager::WriteToFile(content, overlay_file_path);
}
RateLimiterConfig::RateLimiterConfig()
: overlay_file_path_(
absl::StrCat(kDefaultConfigDir, "/", kConfigFilename)) {
LoadConfigLocked(overlay_file_path_);
}
RateLimiterConfig& RateLimiterConfig::Instance() {
static absl::NoDestructor<RateLimiterConfig> instance;
return *instance;
}
void RateLimiterConfig::Init(std::string_view config_dir) {
Instance().InitImpl(config_dir);
}
RedfishRateLimiterModule RateLimiterConfig::GetConfig() {
return Instance().GetConfigImpl();
}
absl::Status RateLimiterConfig::UpdateConfiguration(
const RedfishRateLimiterModule& patch_data, bool replace_bypass_uris) {
return Instance().UpdateConfigurationImpl(patch_data, replace_bypass_uris);
}
void RateLimiterConfig::InitImpl(std::string_view config_dir) {
absl::MutexLock lock(mutex_);
overlay_file_path_ = absl::StrCat(config_dir, "/", kConfigFilename);
config_.Clear();
overlay_config_.Clear();
LoadConfigLocked(overlay_file_path_);
}
RedfishRateLimiterModule RateLimiterConfig::GetConfigImpl() const {
absl::MutexLock lock(mutex_);
return config_;
}
absl::Status RateLimiterConfig::UpdateConfigurationImpl(
const RedfishRateLimiterModule& patch_data, bool replace_bypass_uris) {
RedfishRateLimiterModule new_overlay;
std::string new_overlay_file_path;
{
absl::MutexLock lock(mutex_);
new_overlay.MergeFrom(overlay_config_);
if (replace_bypass_uris) {
new_overlay.clear_bypass_uri();
}
new_overlay.MergeFrom(patch_data);
new_overlay_file_path = overlay_file_path_;
}
ECCLESIA_RETURN_IF_ERROR(
SaveConfigToFile(new_overlay, new_overlay_file_path));
{
absl::MutexLock lock(mutex_);
overlay_config_ = new_overlay;
// Re-derive effective config from base + overlay to ensure consistency,
// especially for repeated fields.
config_ = GetTlbmcConfig().redfish_rate_limiter_module();
config_.MergeFrom(overlay_config_);
}
return absl::OkStatus();
}
void RateLimiterConfig::Reset() { Instance().ResetImpl(); }
void RateLimiterConfig::ResetImpl() {
absl::MutexLock lock(mutex_);
overlay_file_path_ = absl::StrCat(kDefaultConfigDir, "/", kConfigFilename);
config_.Clear();
overlay_config_.Clear();
}
} // namespace milotic_tlbmc