Line data Source code
1 : #include "source/common/config/datasource.h" 2 : 3 : #include "envoy/config/core/v3/base.pb.h" 4 : 5 : #include "source/common/config/utility.h" 6 : 7 : #include "fmt/format.h" 8 : 9 : namespace Envoy { 10 : namespace Config { 11 : namespace DataSource { 12 : 13 : // Default Parameters of the jittered backoff strategy. 14 : static constexpr uint32_t RetryInitialDelayMilliseconds = 1000; 15 : static constexpr uint32_t RetryMaxDelayMilliseconds = 10 * 1000; 16 : static constexpr uint32_t RetryCount = 1; 17 : 18 : std::string read(const envoy::config::core::v3::DataSource& source, bool allow_empty, Api::Api& api, 19 47 : uint64_t max_size) { 20 47 : std::string data; 21 47 : absl::StatusOr<std::string> file_or_error; 22 47 : switch (source.specifier_case()) { 23 0 : case envoy::config::core::v3::DataSource::SpecifierCase::kFilename: 24 0 : if (max_size > 0) { 25 0 : if (!api.fileSystem().fileExists(source.filename())) { 26 0 : throwEnvoyExceptionOrPanic(fmt::format("file {} does not exist", source.filename())); 27 0 : } 28 0 : const ssize_t size = api.fileSystem().fileSize(source.filename()); 29 0 : if (size < 0) { 30 0 : throwEnvoyExceptionOrPanic( 31 0 : absl::StrCat("cannot determine size of file ", source.filename())); 32 0 : } 33 0 : if (static_cast<uint64_t>(size) > max_size) { 34 0 : throwEnvoyExceptionOrPanic(fmt::format("file {} size is {} bytes; maximum is {}", 35 0 : source.filename(), size, max_size)); 36 0 : } 37 0 : } 38 0 : file_or_error = api.fileSystem().fileReadToEnd(source.filename()); 39 0 : THROW_IF_STATUS_NOT_OK(file_or_error, throw); 40 0 : data = file_or_error.value(); 41 0 : break; 42 34 : case envoy::config::core::v3::DataSource::SpecifierCase::kInlineBytes: 43 34 : data = source.inline_bytes(); 44 34 : break; 45 9 : case envoy::config::core::v3::DataSource::SpecifierCase::kInlineString: 46 9 : data = source.inline_string(); 47 9 : break; 48 0 : case envoy::config::core::v3::DataSource::SpecifierCase::kEnvironmentVariable: { 49 0 : const char* environment_variable = std::getenv(source.environment_variable().c_str()); 50 0 : if (environment_variable == nullptr) { 51 0 : throwEnvoyExceptionOrPanic( 52 0 : fmt::format("Environment variable doesn't exist: {}", source.environment_variable())); 53 0 : } 54 0 : data = environment_variable; 55 0 : break; 56 0 : } 57 4 : default: 58 4 : if (!allow_empty) { 59 0 : throwEnvoyExceptionOrPanic( 60 0 : fmt::format("Unexpected DataSource::specifier_case(): {}", source.specifier_case())); 61 0 : } 62 47 : } 63 47 : if (!allow_empty && data.empty()) { 64 0 : throwEnvoyExceptionOrPanic("DataSource cannot be empty"); 65 0 : } 66 47 : return data; 67 47 : } 68 : 69 0 : absl::optional<std::string> getPath(const envoy::config::core::v3::DataSource& source) { 70 0 : return source.specifier_case() == envoy::config::core::v3::DataSource::SpecifierCase::kFilename 71 0 : ? absl::make_optional(source.filename()) 72 0 : : absl::nullopt; 73 0 : } 74 : 75 : RemoteAsyncDataProvider::RemoteAsyncDataProvider( 76 : Upstream::ClusterManager& cm, Init::Manager& manager, 77 : const envoy::config::core::v3::RemoteDataSource& source, Event::Dispatcher& dispatcher, 78 : Random::RandomGenerator& random, bool allow_empty, AsyncDataSourceCb&& callback) 79 : : allow_empty_(allow_empty), callback_(std::move(callback)), 80 : fetcher_(std::make_unique<Config::DataFetcher::RemoteDataFetcher>(cm, source.http_uri(), 81 : source.sha256(), *this)), 82 0 : init_target_("RemoteAsyncDataProvider", [this]() { start(); }), 83 : retries_remaining_( 84 0 : PROTOBUF_GET_WRAPPED_OR_DEFAULT(source.retry_policy(), num_retries, RetryCount)) { 85 : 86 0 : backoff_strategy_ = Utility::prepareJitteredExponentialBackOffStrategy( 87 0 : source, random, RetryInitialDelayMilliseconds, RetryMaxDelayMilliseconds); 88 : 89 0 : retry_timer_ = dispatcher.createTimer([this]() -> void { start(); }); 90 : 91 0 : manager.add(init_target_); 92 0 : } 93 : 94 : } // namespace DataSource 95 : } // namespace Config 96 : } // namespace Envoy