1
#pragma once
2

            
3
#include <memory>
4

            
5
#include "envoy/common/time.h"
6

            
7
#include "source/common/common/assert.h"
8
#include "source/common/protobuf/protobuf.h"
9

            
10
#include "absl/types/optional.h"
11

            
12
namespace Envoy {
13
namespace Config {
14

            
15
/**
16
 * A provider for configuration obtained statically (via static resources in the bootstrap config),
17
 * inline with a higher level resource or dynamically via xDS APIs.
18
 *
19
 * The ConfigProvider is an abstraction layer which higher level components such as the
20
 * HttpConnectionManager, Listener, etc can leverage to interface with Envoy's configuration
21
 * mechanisms. Implementations of this interface build upon lower level abstractions such as
22
 * Envoy::Config::Subscription and Envoy::Config::SubscriptionCallbacks.
23
 *
24
 * The interface exposed below allows xDS providers to share the underlying config protos and
25
 * resulting config implementations (i.e., the ConfigProvider::Config); this enables linear memory
26
 * scaling based on the size of the configuration set, regardless of the number of threads/workers.
27
 *
28
 * Use config() to obtain a shared_ptr to the implementation of the config, and
29
 * ConfigProtoInfoVector() to obtain a reference to the underlying config protos.
30
 */
31
class ConfigProvider {
32
public:
33
  /**
34
   * The "implementation" of the configuration.
35
   * Use config() to obtain a typed object that corresponds to the specific configuration
36
   * represented by this abstract type.
37
   */
38
  class Config {
39
  public:
40
11174
    virtual ~Config() = default;
41
  };
42
  using ConfigConstSharedPtr = std::shared_ptr<const Config>;
43

            
44
  /**
45
   * The type of API represented by a ConfigProvider.
46
   */
47
  enum class ApiType {
48
    /**
49
     * A "Full" API delivers a complete configuration as part of each resource (top level
50
     * config proto); i.e., each resource contains the whole representation of the config intent. An
51
     * example of this type of API is RDS.
52
     */
53
    Full,
54
    /**
55
     * A "Delta" API delivers a subset of the config intent as part of each resource (top level
56
     * config proto). Examples of this type of API are CDS, LDS and SRDS.
57
     */
58
    Delta
59
  };
60

            
61
  using ConfigProtoVector = std::vector<const Protobuf::Message*>;
62
  /**
63
   * Stores the config protos associated with a "Delta" API.
64
   */
65
  template <typename P> struct ConfigProtoInfoVector {
66
    const std::vector<const P*> config_protos_;
67
  };
68

            
69
11108
  virtual ~ConfigProvider() = default;
70

            
71
  /**
72
   * The type of API.
73
   */
74
  virtual ApiType apiType() const PURE;
75

            
76
  /**
77
   * Returns a ConfigProtoInfoVector associated with a ApiType::Delta provider.
78
   * @return absl::optional<ConfigProtoInfoVector> an optional ConfigProtoInfoVector; the value is
79
   * set when a config is available.
80
   */
81
12
  template <typename P> absl::optional<ConfigProtoInfoVector<P>> configProtoInfoVector() const {
82
12
    static_assert(std::is_base_of<Protobuf::Message, P>::value,
83
12
                  "Proto type must derive from Protobuf::Message");
84

            
85
12
    const ConfigProtoVector config_protos = getConfigProtos();
86
12
    if (config_protos.empty()) {
87
2
      return absl::nullopt;
88
2
    }
89
10
    std::vector<const P*> ret_protos;
90
10
    ret_protos.reserve(config_protos.size());
91
11
    for (const auto* elem : config_protos) {
92
11
      ret_protos.push_back(static_cast<const P*>(elem));
93
11
    }
94
10
    return ConfigProtoInfoVector<P>{std::move(ret_protos)};
95
12
  }
96

            
97
  /**
98
   * Returns the Config corresponding to the provider.
99
   * @return std::shared_ptr<const C> a shared pointer to the Config.
100
   */
101
271
  template <typename C> std::shared_ptr<const C> config() const {
102
271
    static_assert(std::is_base_of<Config, C>::value,
103
271
                  "Config type must derive from ConfigProvider::Config");
104

            
105
271
    return std::dynamic_pointer_cast<const C>(getConfig());
106
271
  }
107

            
108
  /**
109
   * Returns the timestamp associated with the last update to the Config.
110
   * @return SystemTime the timestamp corresponding to the last config update.
111
   */
112
  virtual SystemTime lastUpdated() const PURE;
113

            
114
protected:
115
  /**
116
   * Returns the config protos associated with the provider.
117
   * @return const ConfigProtoVector the config protos corresponding to the Config instantiated by
118
   *         the provider.
119
   */
120
  virtual ConfigProtoVector getConfigProtos() const { PANIC("not implemented"); }
121

            
122
  /**
123
   * Returns the config implementation associated with the provider.
124
   * @return ConfigConstSharedPtr the config as the base type.
125
   */
126
  virtual ConfigConstSharedPtr getConfig() const PURE;
127
};
128

            
129
using ConfigProviderPtr = std::unique_ptr<ConfigProvider>;
130

            
131
} // namespace Config
132
} // namespace Envoy