Coverage Report

Created: 2023-11-12 09:30

/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