/proc/self/cwd/source/common/config/datasource.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include "envoy/api/api.h" |
4 | | #include "envoy/common/random_generator.h" |
5 | | #include "envoy/config/core/v3/base.pb.h" |
6 | | #include "envoy/event/deferred_deletable.h" |
7 | | #include "envoy/init/manager.h" |
8 | | #include "envoy/upstream/cluster_manager.h" |
9 | | |
10 | | #include "source/common/common/backoff_strategy.h" |
11 | | #include "source/common/common/empty_string.h" |
12 | | #include "source/common/common/enum_to_int.h" |
13 | | #include "source/common/config/remote_data_fetcher.h" |
14 | | #include "source/common/init/target_impl.h" |
15 | | |
16 | | #include "absl/types/optional.h" |
17 | | |
18 | | namespace Envoy { |
19 | | namespace Config { |
20 | | namespace DataSource { |
21 | | |
22 | | /** |
23 | | * Read contents of the DataSource. |
24 | | * @param source data source. |
25 | | * @param allow_empty return an empty string if no DataSource case is specified. |
26 | | * @param api reference to the Api object |
27 | | * @param max_size max size limit of file to read, default 0 means no limit, and if the file data |
28 | | * would exceed the limit, it will throw a EnvoyException. |
29 | | * @return std::string with DataSource contents. |
30 | | * @throw EnvoyException if no DataSource case is specified and !allow_empty. |
31 | | */ |
32 | | std::string read(const envoy::config::core::v3::DataSource& source, bool allow_empty, Api::Api& api, |
33 | | uint64_t max_size = 0); |
34 | | |
35 | | /** |
36 | | * @param source data source. |
37 | | * @return absl::optional<std::string> path to DataSource if a filename, otherwise absl::nullopt. |
38 | | */ |
39 | | absl::optional<std::string> getPath(const envoy::config::core::v3::DataSource& source); |
40 | | |
41 | | /** |
42 | | * Callback for async data source. |
43 | | */ |
44 | | using AsyncDataSourceCb = std::function<void(const std::string&)>; |
45 | | |
46 | | class LocalAsyncDataProvider { |
47 | | public: |
48 | | LocalAsyncDataProvider(Init::Manager& manager, const envoy::config::core::v3::DataSource& source, |
49 | | bool allow_empty, Api::Api& api, AsyncDataSourceCb&& callback) |
50 | | : init_target_("LocalAsyncDataProvider", [this, &source, allow_empty, &api, callback]() { |
51 | | callback(DataSource::read(source, allow_empty, api)); |
52 | | init_target_.ready(); |
53 | 0 | }) { |
54 | 0 | manager.add(init_target_); |
55 | 0 | } |
56 | | |
57 | 0 | ~LocalAsyncDataProvider() { init_target_.ready(); } |
58 | | |
59 | | private: |
60 | | Init::TargetImpl init_target_; |
61 | | }; |
62 | | |
63 | | using LocalAsyncDataProviderPtr = std::unique_ptr<LocalAsyncDataProvider>; |
64 | | |
65 | | class RemoteAsyncDataProvider : public Event::DeferredDeletable, |
66 | | public Config::DataFetcher::RemoteDataFetcherCallback, |
67 | | public Logger::Loggable<Logger::Id::config> { |
68 | | public: |
69 | | RemoteAsyncDataProvider(Upstream::ClusterManager& cm, Init::Manager& manager, |
70 | | const envoy::config::core::v3::RemoteDataSource& source, |
71 | | Event::Dispatcher& dispatcher, Random::RandomGenerator& random, |
72 | | bool allow_empty, AsyncDataSourceCb&& callback); |
73 | | |
74 | 0 | ~RemoteAsyncDataProvider() override { |
75 | 0 | init_target_.ready(); |
76 | 0 | if (retry_timer_) { |
77 | 0 | retry_timer_->disableTimer(); |
78 | 0 | } |
79 | 0 | } |
80 | | |
81 | | // Config::DataFetcher::RemoteDataFetcherCallback |
82 | 0 | void onSuccess(const std::string& data) override { |
83 | 0 | callback_(data); |
84 | 0 | init_target_.ready(); |
85 | 0 | } |
86 | | |
87 | | // Config::DataFetcher::RemoteDataFetcherCallback |
88 | 0 | void onFailure(Config::DataFetcher::FailureReason failure) override { |
89 | 0 | ENVOY_LOG(debug, "Failed to fetch remote data, failure reason: {}", enumToInt(failure)); |
90 | 0 | if (retries_remaining_-- == 0) { |
91 | 0 | ENVOY_LOG(warn, "Retry limit exceeded for fetching data from remote data source."); |
92 | 0 | if (allow_empty_) { |
93 | 0 | callback_(EMPTY_STRING); |
94 | 0 | } |
95 | | // We need to allow server startup to continue. |
96 | 0 | init_target_.ready(); |
97 | 0 | return; |
98 | 0 | } |
99 | | |
100 | 0 | const auto retry_ms = std::chrono::milliseconds(backoff_strategy_->nextBackOffMs()); |
101 | 0 | ENVOY_LOG(debug, "Remote data provider will retry in {} ms.", retry_ms.count()); |
102 | 0 | retry_timer_->enableTimer(retry_ms); |
103 | 0 | } |
104 | | |
105 | | private: |
106 | 0 | void start() { fetcher_->fetch(); } |
107 | | |
108 | | bool allow_empty_; |
109 | | AsyncDataSourceCb callback_; |
110 | | const Config::DataFetcher::RemoteDataFetcherPtr fetcher_; |
111 | | Init::TargetImpl init_target_; |
112 | | |
113 | | Event::TimerPtr retry_timer_; |
114 | | BackOffStrategyPtr backoff_strategy_; |
115 | | uint32_t retries_remaining_; |
116 | | }; |
117 | | |
118 | | using RemoteAsyncDataProviderPtr = std::unique_ptr<RemoteAsyncDataProvider>; |
119 | | |
120 | | } // namespace DataSource |
121 | | } // namespace Config |
122 | | } // namespace Envoy |