| #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 |