1
#pragma once
2

            
3
#include "envoy/common/random_generator.h"
4
#include "envoy/config/subscription.h"
5
#include "envoy/event/dispatcher.h"
6
#include "envoy/service/discovery/v3/discovery.pb.h"
7

            
8
#include "source/common/config/api_version.h"
9
#include "source/common/config/type_to_endpoint.h"
10
#include "source/common/config/utility.h"
11
#include "source/extensions/config_subscription/rest/rest_api_fetcher.h"
12

            
13
namespace Envoy {
14
namespace Config {
15

            
16
/**
17
 * REST implementation of the API Subscription interface. This fetches the API via periodic polling
18
 * with jitter (based on RestApiFetcher). The REST requests are POSTs of the JSON canonical
19
 * representation of the DiscoveryRequest proto and the responses are in the form of the JSON
20
 * canonical representation of DiscoveryResponse. This implementation is responsible for translating
21
 * between the proto serializable objects in the Subscription API and the REST JSON representation.
22
 */
23
class HttpSubscriptionImpl : public Http::RestApiFetcher,
24
                             public Config::Subscription,
25
                             Logger::Loggable<Logger::Id::config> {
26
public:
27
  HttpSubscriptionImpl(const LocalInfo::LocalInfo& local_info, Upstream::ClusterManager& cm,
28
                       const std::string& remote_cluster_name, Event::Dispatcher& dispatcher,
29
                       Random::RandomGenerator& random, std::chrono::milliseconds refresh_interval,
30
                       std::chrono::milliseconds request_timeout,
31
                       const Protobuf::MethodDescriptor& service_method, absl::string_view type_url,
32
                       SubscriptionCallbacks& callbacks,
33
                       OpaqueResourceDecoderSharedPtr resource_decoder, SubscriptionStats stats,
34
                       std::chrono::milliseconds init_fetch_timeout,
35
                       ProtobufMessage::ValidationVisitor& validation_visitor);
36

            
37
  // Config::Subscription
38
  void start(const absl::flat_hash_set<std::string>& resource_names) override;
39
  void
40
  updateResourceInterest(const absl::flat_hash_set<std::string>& update_to_these_names) override;
41
  void requestOnDemandUpdate(const absl::flat_hash_set<std::string>&) override {
42
    ENVOY_BUG(false, "unexpected request for on demand update");
43
  }
44

            
45
  // Http::RestApiFetcher
46
  void createRequest(Http::RequestMessage& request) override;
47
  void parseResponse(const Http::ResponseMessage& response) override;
48
  void onFetchComplete() override;
49
  void onFetchFailure(Config::ConfigUpdateFailureReason reason, const EnvoyException* e) override;
50

            
51
private:
52
  void handleFailure(Config::ConfigUpdateFailureReason reason, const EnvoyException* e);
53
  void disableInitFetchTimeoutTimer();
54

            
55
  std::string path_;
56
  Protobuf::RepeatedPtrField<std::string> resources_;
57
  envoy::service::discovery::v3::DiscoveryRequest request_;
58
  Config::SubscriptionCallbacks& callbacks_;
59
  Config::OpaqueResourceDecoderSharedPtr resource_decoder_;
60
  SubscriptionStats stats_;
61
  Event::Dispatcher& dispatcher_;
62
  std::chrono::milliseconds init_fetch_timeout_;
63
  Event::TimerPtr init_fetch_timeout_timer_;
64
  ProtobufMessage::ValidationVisitor& validation_visitor_;
65
};
66

            
67
class HttpSubscriptionFactory : public ConfigSubscriptionFactory {
68
public:
69
6
  std::string name() const override { return "envoy.config_subscription.rest"; }
70

            
71
  /**
72
   * Extract refresh_delay as a std::chrono::milliseconds from
73
   * envoy::config::core::v3::ApiConfigSource.
74
   */
75
  static std::chrono::milliseconds
76
  apiConfigSourceRefreshDelay(const envoy::config::core::v3::ApiConfigSource& api_config_source);
77

            
78
  /**
79
   * Extract request_timeout as a std::chrono::milliseconds from
80
   * envoy::config::core::v3::ApiConfigSource. If request_timeout isn't set in the config source, a
81
   * default value of 1s will be returned.
82
   */
83
  static std::chrono::milliseconds
84
  apiConfigSourceRequestTimeout(const envoy::config::core::v3::ApiConfigSource& api_config_source);
85

            
86
4
  SubscriptionPtr create(SubscriptionData& data) override {
87
4
    const envoy::config::core::v3::ApiConfigSource& api_config_source =
88
4
        data.config_.api_config_source();
89
4
    return std::make_unique<HttpSubscriptionImpl>(
90
4
        data.local_info_, data.cm_, api_config_source.cluster_names()[0], data.dispatcher_,
91
4
        data.api_.randomGenerator(), apiConfigSourceRefreshDelay(api_config_source),
92
4
        apiConfigSourceRequestTimeout(api_config_source), restMethod(data.type_url_),
93
4
        data.type_url_, data.callbacks_, data.resource_decoder_, data.stats_,
94
4
        Utility::configSourceInitialFetchTimeout(data.config_), data.validation_visitor_);
95
4
  }
96
};
97

            
98
} // namespace Config
99
} // namespace Envoy