Line data Source code
1 : #pragma once 2 : 3 : #include "envoy/api/api.h" 4 : #include "envoy/config/core/v3/config_source.pb.h" 5 : #include "envoy/config/subscription.h" 6 : #include "envoy/config/subscription_factory.h" 7 : #include "envoy/event/dispatcher.h" 8 : #include "envoy/filesystem/filesystem.h" 9 : #include "envoy/protobuf/message_validator.h" 10 : 11 : #include "source/common/common/logger.h" 12 : #include "source/common/config/watched_directory.h" 13 : 14 : namespace Envoy { 15 : namespace Config { 16 : 17 : envoy::config::core::v3::PathConfigSource makePathConfigSource(const std::string& path); 18 : 19 : /** 20 : * Filesystem inotify implementation of the API Subscription interface. This allows the API to be 21 : * consumed on filesystem changes to files containing the JSON canonical representation of 22 : * lists of xDS resources. 23 : */ 24 : class FilesystemSubscriptionImpl : public Config::Subscription, 25 : protected Logger::Loggable<Logger::Id::config> { 26 : public: 27 : FilesystemSubscriptionImpl(Event::Dispatcher& dispatcher, 28 : const envoy::config::core::v3::PathConfigSource& path_config_source, 29 : SubscriptionCallbacks& callbacks, 30 : OpaqueResourceDecoderSharedPtr resource_decoder, 31 : SubscriptionStats stats, 32 : ProtobufMessage::ValidationVisitor& validation_visitor, Api::Api& api); 33 : 34 : // Config::Subscription 35 : // We report all discovered resources in the watched file, so the resource names arguments are 36 : // unused, and updateResourceInterest is a no-op (other than updating a stat). 37 : void start(const absl::flat_hash_set<std::string>&) override; 38 : void updateResourceInterest(const absl::flat_hash_set<std::string>&) override; 39 0 : void requestOnDemandUpdate(const absl::flat_hash_set<std::string>&) override { 40 0 : ENVOY_BUG(false, "unexpected request for on demand update"); 41 0 : } 42 : 43 : protected: 44 : virtual std::string refreshInternal(ProtobufTypes::MessagePtr* config_update); 45 : void refresh(); 46 : void configRejected(const EnvoyException& e, const std::string& message); 47 : 48 : bool started_{}; 49 : const std::string path_; 50 : std::unique_ptr<Filesystem::Watcher> file_watcher_; 51 : WatchedDirectoryPtr directory_watcher_; 52 : SubscriptionCallbacks& callbacks_; 53 : OpaqueResourceDecoderSharedPtr resource_decoder_; 54 : SubscriptionStats stats_; 55 : Api::Api& api_; 56 : ProtobufMessage::ValidationVisitor& validation_visitor_; 57 : }; 58 : 59 : // Currently a FilesystemSubscriptionImpl subclass, but this will need to change when we support 60 : // non-inline collection resources. 61 : class FilesystemCollectionSubscriptionImpl : public FilesystemSubscriptionImpl { 62 : public: 63 : FilesystemCollectionSubscriptionImpl( 64 : Event::Dispatcher& dispatcher, 65 : const envoy::config::core::v3::PathConfigSource& path_config_source, 66 : SubscriptionCallbacks& callbacks, OpaqueResourceDecoderSharedPtr resource_decoder, 67 : SubscriptionStats stats, ProtobufMessage::ValidationVisitor& validation_visitor, 68 : Api::Api& api); 69 : 70 : std::string refreshInternal(ProtobufTypes::MessagePtr* config_update) override; 71 : }; 72 : 73 : class FilesystemSubscriptionFactory : public ConfigSubscriptionFactory { 74 : public: 75 13 : std::string name() const override { return "envoy.config_subscription.filesystem"; } 76 : 77 70 : SubscriptionPtr create(SubscriptionData& data) override { 78 70 : if (data.config_.config_source_specifier_case() == 79 70 : envoy::config::core::v3::ConfigSource::ConfigSourceSpecifierCase::kPath) { 80 0 : return std::make_unique<Config::FilesystemSubscriptionImpl>( 81 0 : data.dispatcher_, makePathConfigSource(data.config_.path()), data.callbacks_, 82 0 : data.resource_decoder_, data.stats_, data.validation_visitor_, data.api_); 83 70 : } else { 84 70 : ASSERT(data.config_.config_source_specifier_case() == 85 70 : envoy::config::core::v3::ConfigSource::ConfigSourceSpecifierCase::kPathConfigSource); 86 70 : return std::make_unique<Config::FilesystemSubscriptionImpl>( 87 70 : data.dispatcher_, data.config_.path_config_source(), data.callbacks_, 88 70 : data.resource_decoder_, data.stats_, data.validation_visitor_, data.api_); 89 70 : } 90 70 : } 91 : }; 92 : 93 : class FilesystemCollectionSubscriptionFactory : public ConfigSubscriptionFactory { 94 : public: 95 13 : std::string name() const override { return "envoy.config_subscription.filesystem_collection"; } 96 : 97 0 : SubscriptionPtr create(SubscriptionData& data) override { 98 0 : return std::make_unique<Config::FilesystemCollectionSubscriptionImpl>( 99 0 : data.dispatcher_, makePathConfigSource(data.config_.path()), data.callbacks_, 100 0 : data.resource_decoder_, data.stats_, data.validation_visitor_, data.api_); 101 0 : } 102 : }; 103 : 104 : } // namespace Config 105 : } // namespace Envoy