1
#pragma once
2

            
3
#include <memory>
4
#include <string>
5

            
6
#include "envoy/config/core/v3/config_source.pb.h"
7
#include "envoy/config/subscription.h"
8
#include "envoy/rds/route_config_provider.h"
9
#include "envoy/rds/route_config_update_receiver.h"
10
#include "envoy/server/factory_context.h"
11
#include "envoy/stats/scope.h"
12

            
13
#include "source/common/grpc/common.h"
14
#include "source/common/init/manager_impl.h"
15
#include "source/common/init/target_impl.h"
16
#include "source/common/init/watcher_impl.h"
17
#include "source/common/rds/route_config_provider_manager.h"
18

            
19
#include "absl/types/optional.h"
20

            
21
namespace Envoy {
22
namespace Rds {
23

            
24
/**
25
 * All RDS stats. @see stats_macros.h
26
 */
27
#define ALL_RDS_STATS(COUNTER, GAUGE)                                                              \
28
380
  COUNTER(config_reload)                                                                           \
29
380
  COUNTER(update_empty)                                                                            \
30
380
  GAUGE(config_reload_time_ms, NeverImport)
31

            
32
/**
33
 * Struct definition for all RDS stats. @see stats_macros.h
34
 */
35
struct RdsStats {
36
  ALL_RDS_STATS(GENERATE_COUNTER_STRUCT, GENERATE_GAUGE_STRUCT)
37
};
38

            
39
/**
40
 * A class that fetches the route configuration dynamically using the RDS API and updates them to
41
 * RDS config providers.
42
 */
43
class RdsRouteConfigSubscription : Envoy::Config::SubscriptionCallbacks,
44
                                   protected Logger::Loggable<Logger::Id::rds> {
45
public:
46
  static absl::StatusOr<std::unique_ptr<RdsRouteConfigSubscription>>
47
  create(RouteConfigUpdatePtr&& config_update,
48
         Envoy::Config::OpaqueResourceDecoderSharedPtr&& resource_decoder,
49
         const envoy::config::core::v3::ConfigSource& config_source,
50
         const std::string& route_config_name, const uint64_t manager_identifier,
51
         Server::Configuration::ServerFactoryContext& factory_context,
52
         const std::string& stat_prefix, const std::string& rds_type,
53
         RouteConfigProviderManager& route_config_provider_manager);
54

            
55
  ~RdsRouteConfigSubscription() override;
56

            
57
1132
  RouteConfigProvider*& routeConfigProvider() { return route_config_provider_; }
58

            
59
380
  RouteConfigUpdatePtr& routeConfigUpdate() { return config_update_info_; }
60

            
61
380
  const Init::Target& initTarget() { return parent_init_target_; }
62

            
63
protected:
64
  RdsRouteConfigSubscription(RouteConfigUpdatePtr&& config_update,
65
                             Envoy::Config::OpaqueResourceDecoderSharedPtr&& resource_decoder,
66
                             const envoy::config::core::v3::ConfigSource& config_source,
67
                             const std::string& route_config_name,
68
                             const uint64_t manager_identifier,
69
                             Server::Configuration::ServerFactoryContext& factory_context,
70
                             const std::string& stat_prefix, const std::string& rds_type,
71
                             RouteConfigProviderManager& route_config_provider_manager,
72
                             absl::Status& creation_status);
73

            
74
private:
75
  // Config::SubscriptionCallbacks
76
  absl::Status onConfigUpdate(const std::vector<Envoy::Config::DecodedResourceRef>& resources,
77
                              const std::string& version_info) override;
78

            
79
  absl::Status onConfigUpdate(const std::vector<Envoy::Config::DecodedResourceRef>& added_resources,
80
                              const Protobuf::RepeatedPtrField<std::string>& removed_resources,
81
                              const std::string&) override;
82

            
83
  void onConfigUpdateFailed(Envoy::Config::ConfigUpdateFailureReason reason,
84
                            const EnvoyException*) override;
85

            
86
  virtual absl::Status beforeProviderUpdate(std::unique_ptr<Init::ManagerImpl>&,
87
6
                                            std::unique_ptr<Cleanup>&) {
88
6
    return absl::OkStatus();
89
6
  }
90
6
  virtual absl::Status afterProviderUpdate() { return absl::OkStatus(); }
91

            
92
protected:
93
  const std::string route_config_name_;
94
  // This scope must outlive the subscription_ below as the subscription has derived stats.
95
  Stats::ScopeSharedPtr scope_;
96
  Envoy::Config::SubscriptionPtr subscription_;
97
  Server::Configuration::ServerFactoryContext& factory_context_;
98

            
99
  // Init target used to notify the parent init manager that the subscription [and its sub resource]
100
  // is ready.
101
  Init::SharedTargetImpl parent_init_target_;
102
  // Init watcher on RDS and VHDS ready event. This watcher marks parent_init_target_ ready.
103
  Init::WatcherImpl local_init_watcher_;
104
  // Target which starts the RDS subscription.
105
  Init::TargetImpl local_init_target_;
106
  Init::ManagerImpl local_init_manager_;
107
  const std::string stat_prefix_;
108
  const std::string rds_type_;
109
  RdsStats stats_;
110
  RouteConfigProviderManager& route_config_provider_manager_;
111
  const uint64_t manager_identifier_;
112
  RouteConfigProvider* route_config_provider_{nullptr};
113
  RouteConfigUpdatePtr config_update_info_;
114
  Envoy::Config::OpaqueResourceDecoderSharedPtr resource_decoder_;
115
};
116

            
117
using RdsRouteConfigSubscriptionSharedPtr = std::shared_ptr<RdsRouteConfigSubscription>;
118

            
119
} // namespace Rds
120
} // namespace Envoy