Line data Source code
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 configProtoInfo() to 29 : * obtain a reference to the underlying config proto and version (applicable only to dynamic config 30 : * providers). 31 : */ 32 : class ConfigProvider { 33 : public: 34 : /** 35 : * The "implementation" of the configuration. 36 : * Use config() to obtain a typed object that corresponds to the specific configuration 37 : * represented by this abstract type. 38 : */ 39 : class Config { 40 : public: 41 170 : virtual ~Config() = default; 42 : }; 43 : using ConfigConstSharedPtr = std::shared_ptr<const Config>; 44 : 45 : /** 46 : * The type of API represented by a ConfigProvider. 47 : */ 48 : enum class ApiType { 49 : /** 50 : * A "Full" API delivers a complete configuration as part of each resource (top level 51 : * config proto); i.e., each resource contains the whole representation of the config intent. An 52 : * example of this type of API is RDS. 53 : */ 54 : Full, 55 : /** 56 : * A "Delta" API delivers a subset of the config intent as part of each resource (top level 57 : * config proto). Examples of this type of API are CDS, LDS and SRDS. 58 : */ 59 : Delta 60 : }; 61 : 62 : /** 63 : * Stores the config proto as well as the associated version. 64 : */ 65 : template <typename P> struct ConfigProtoInfo { 66 : const P& config_proto_; 67 : 68 : // Only populated by dynamic config providers. 69 : std::string version_; 70 : }; 71 : 72 : using ConfigProtoVector = std::vector<const Protobuf::Message*>; 73 : /** 74 : * Stores the config protos associated with a "Delta" API. 75 : */ 76 : template <typename P> struct ConfigProtoInfoVector { 77 : const std::vector<const P*> config_protos_; 78 : 79 : // Only populated by dynamic config providers. 80 : std::string version_; 81 : }; 82 : 83 170 : virtual ~ConfigProvider() = default; 84 : 85 : /** 86 : * The type of API. 87 : */ 88 : virtual ApiType apiType() const PURE; 89 : 90 : /** 91 : * Returns a ConfigProtoInfo associated with a ApiType::Full provider. 92 : * @return absl::optional<ConfigProtoInfo<P>> an optional ConfigProtoInfo; the value is set when a 93 : * config is available. 94 : */ 95 : template <typename P> absl::optional<ConfigProtoInfo<P>> configProtoInfo() const { 96 : static_assert(std::is_base_of<Protobuf::Message, P>::value, 97 : "Proto type must derive from Protobuf::Message"); 98 : 99 : const auto* config_proto = dynamic_cast<const P*>(getConfigProto()); 100 : if (config_proto == nullptr) { 101 : return absl::nullopt; 102 : } 103 : return ConfigProtoInfo<P>{*config_proto, getConfigVersion()}; 104 : } 105 : 106 : /** 107 : * Returns a ConfigProtoInfoVector associated with a ApiType::Delta provider. 108 : * @return absl::optional<ConfigProtoInfoVector> an optional ConfigProtoInfoVector; the value is 109 : * set when a config is available. 110 : */ 111 0 : template <typename P> absl::optional<ConfigProtoInfoVector<P>> configProtoInfoVector() const { 112 0 : static_assert(std::is_base_of<Protobuf::Message, P>::value, 113 0 : "Proto type must derive from Protobuf::Message"); 114 : 115 0 : const ConfigProtoVector config_protos = getConfigProtos(); 116 0 : if (config_protos.empty()) { 117 0 : return absl::nullopt; 118 0 : } 119 0 : std::vector<const P*> ret_protos; 120 0 : ret_protos.reserve(config_protos.size()); 121 0 : for (const auto* elem : config_protos) { 122 0 : ret_protos.push_back(static_cast<const P*>(elem)); 123 0 : } 124 0 : return ConfigProtoInfoVector<P>{std::move(ret_protos), getConfigVersion()}; 125 0 : } 126 : 127 : /** 128 : * Returns the Config corresponding to the provider. 129 : * @return std::shared_ptr<const C> a shared pointer to the Config. 130 : */ 131 0 : template <typename C> std::shared_ptr<const C> config() const { 132 0 : static_assert(std::is_base_of<Config, C>::value, 133 0 : "Config type must derive from ConfigProvider::Config"); 134 : 135 0 : return std::dynamic_pointer_cast<const C>(getConfig()); 136 0 : } 137 : 138 : /** 139 : * Returns the timestamp associated with the last update to the Config. 140 : * @return SystemTime the timestamp corresponding to the last config update. 141 : */ 142 : virtual SystemTime lastUpdated() const PURE; 143 : 144 : protected: 145 : /** 146 : * Returns the config proto associated with the provider. 147 : * @return Protobuf::Message* the config proto corresponding to the Config instantiated by the 148 : * provider. 149 : */ 150 0 : virtual const Protobuf::Message* getConfigProto() const { return nullptr; } 151 : 152 : /** 153 : * Returns the config protos associated with the provider. 154 : * @return const ConfigProtoVector the config protos corresponding to the Config instantiated by 155 : * the provider. 156 : */ 157 0 : virtual ConfigProtoVector getConfigProtos() const { PANIC("not implemented"); } 158 : 159 : /** 160 : * Returns the config version associated with the provider. 161 : * @return std::string the config version. 162 : */ 163 0 : virtual std::string getConfigVersion() const { return ""; } 164 : 165 : /** 166 : * Returns the config implementation associated with the provider. 167 : * @return ConfigConstSharedPtr the config as the base type. 168 : */ 169 : virtual ConfigConstSharedPtr getConfig() const PURE; 170 : }; 171 : 172 : using ConfigProviderPtr = std::unique_ptr<ConfigProvider>; 173 : 174 : } // namespace Config 175 : } // namespace Envoy