1
#pragma once
2

            
3
#include <array>
4
#include <atomic>
5
#include <chrono>
6
#include <cstdint>
7
#include <functional>
8
#include <list>
9
#include <memory>
10
#include <string>
11
#include <utility>
12
#include <vector>
13

            
14
#include "envoy/config/cluster/v3/cluster.pb.h"
15
#include "envoy/config/typed_metadata.h"
16
#include "envoy/event/timer.h"
17
#include "envoy/local_info/local_info.h"
18
#include "envoy/network/dns.h"
19
#include "envoy/runtime/runtime.h"
20
#include "envoy/secret/secret_manager.h"
21
#include "envoy/server/options.h"
22
#include "envoy/server/transport_socket_config.h"
23
#include "envoy/ssl/context_manager.h"
24
#include "envoy/stats/scope.h"
25
#include "envoy/thread_local/thread_local.h"
26
#include "envoy/upstream/cluster_factory.h"
27
#include "envoy/upstream/cluster_manager.h"
28
#include "envoy/upstream/health_checker.h"
29
#include "envoy/upstream/load_balancer.h"
30
#include "envoy/upstream/locality.h"
31
#include "envoy/upstream/upstream.h"
32

            
33
#include "source/common/common/callback_impl.h"
34
#include "source/common/common/enum_to_int.h"
35
#include "source/common/common/logger.h"
36
#include "source/common/config/metadata.h"
37
#include "source/common/config/utility.h"
38
#include "source/common/config/well_known_names.h"
39
#include "source/common/network/utility.h"
40
#include "source/common/protobuf/utility.h"
41
#include "source/common/stats/isolated_store_impl.h"
42
#include "source/common/upstream/load_balancer_context_base.h"
43
#include "source/common/upstream/outlier_detection_impl.h"
44
#include "source/common/upstream/resource_manager_impl.h"
45
#include "source/common/upstream/upstream_impl.h"
46
#include "source/server/transport_socket_config_impl.h"
47

            
48
namespace Envoy {
49
namespace Upstream {
50

            
51
class ClusterFactoryContextImpl : public ClusterFactoryContext {
52
public:
53
  using LazyCreateDnsResolver = std::function<Network::DnsResolverSharedPtr()>;
54

            
55
  ClusterFactoryContextImpl(Server::Configuration::ServerFactoryContext& server_context,
56
                            LazyCreateDnsResolver dns_resolver_fn,
57
                            Outlier::EventLoggerSharedPtr outlier_event_logger, bool added_via_api)
58
18303
      : server_context_(server_context), dns_resolver_fn_(dns_resolver_fn),
59
18303
        outlier_event_logger_(std::move(outlier_event_logger)),
60
        validation_visitor_(
61
18303
            added_via_api ? server_context.messageValidationContext().dynamicValidationVisitor()
62
18303
                          : server_context.messageValidationContext().staticValidationVisitor()),
63
18303
        added_via_api_(added_via_api) {}
64

            
65
  // ClusterFactoryContext
66
203165
  Server::Configuration::ServerFactoryContext& serverFactoryContext() override {
67
203165
    return server_context_;
68
203165
  }
69
19640
  ProtobufMessage::ValidationVisitor& messageValidationVisitor() override {
70
19640
    return validation_visitor_;
71
19640
  }
72
477
  Network::DnsResolverSharedPtr dnsResolver() override {
73
477
    if (!dns_resolver_) {
74
477
      dns_resolver_ = dns_resolver_fn_();
75
477
    }
76
477
    return dns_resolver_;
77
477
  }
78
17791
  Outlier::EventLoggerSharedPtr outlierEventLogger() override { return outlier_event_logger_; }
79
18275
  bool addedViaApi() override { return added_via_api_; }
80

            
81
private:
82
  Server::Configuration::ServerFactoryContext& server_context_;
83
  Network::DnsResolverSharedPtr dns_resolver_;
84
  LazyCreateDnsResolver dns_resolver_fn_;
85
  Outlier::EventLoggerSharedPtr outlier_event_logger_;
86
  ProtobufMessage::ValidationVisitor& validation_visitor_;
87
  const bool added_via_api_;
88
};
89

            
90
/**
91
 * Base class for all cluster factory implementation. This class can be directly extended if the
92
 * custom cluster does not have any custom configuration. For custom cluster with custom
93
 * configuration, use ConfigurableClusterFactoryBase instead.
94
 */
95
class ClusterFactoryImplBase : public ClusterFactory {
96
public:
97
  using LazyCreateDnsResolver = std::function<Network::DnsResolverSharedPtr()>;
98
  /**
99
   * Static method to get the registered cluster factory and create an instance of cluster.
100
   */
101
  static absl::StatusOr<std::pair<ClusterSharedPtr, ThreadAwareLoadBalancerPtr>>
102
  create(const envoy::config::cluster::v3::Cluster& cluster,
103
         Server::Configuration::ServerFactoryContext& server_context,
104
         LazyCreateDnsResolver dns_resolver_fn, Outlier::EventLoggerSharedPtr outlier_event_logger,
105
         bool added_via_api);
106

            
107
  /**
108
   * Create a dns resolver to be used by the cluster.
109
   */
110
  absl::StatusOr<Network::DnsResolverSharedPtr>
111
  selectDnsResolver(const envoy::config::cluster::v3::Cluster& cluster,
112
                    ClusterFactoryContext& context);
113

            
114
  absl::StatusOr<Network::DnsResolverSharedPtr>
115
  selectDnsResolver(const envoy::config::core::v3::TypedExtensionConfig& typed_dns_resolver_config,
116
                    ClusterFactoryContext& context);
117

            
118
  // Upstream::ClusterFactory
119
  absl::StatusOr<std::pair<ClusterSharedPtr, ThreadAwareLoadBalancerPtr>>
120
  create(const envoy::config::cluster::v3::Cluster& cluster,
121
         ClusterFactoryContext& context) override;
122
4074
  std::string name() const override { return name_; }
123

            
124
protected:
125
1558
  ClusterFactoryImplBase(const std::string& name) : name_(name) {}
126

            
127
private:
128
  /**
129
   * Create an instance of ClusterImplBase or return failure.
130
   */
131
  virtual absl::StatusOr<std::pair<ClusterImplBaseSharedPtr, ThreadAwareLoadBalancerPtr>>
132
  createClusterImpl(const envoy::config::cluster::v3::Cluster& cluster,
133
                    ClusterFactoryContext& context) PURE;
134
  const std::string name_;
135
};
136

            
137
/**
138
 * Common base class for custom cluster factory with custom configuration.
139
 * @param ConfigProto is the configuration protobuf.
140
 */
141
template <class ConfigProto> class ConfigurableClusterFactoryBase : public ClusterFactoryImplBase {
142
public:
143
  /**
144
   * @return ProtobufTypes::MessagePtr create empty config proto message.
145
   */
146
492
  virtual ProtobufTypes::MessagePtr createEmptyConfigProto() {
147
492
    return std::make_unique<ConfigProto>();
148
492
  }
149

            
150
107
  std::set<std::string> configTypes() override {
151
107
    auto ptr = createEmptyConfigProto();
152
107
    ASSERT(ptr != nullptr);
153
107
    Protobuf::ReflectableMessage reflectable_message = createReflectableMessage(*ptr);
154
107
    return {std::string(reflectable_message->GetDescriptor()->full_name())};
155
107
  }
156

            
157
protected:
158
378
  ConfigurableClusterFactoryBase(const std::string& name) : ClusterFactoryImplBase(name) {}
159

            
160
private:
161
  absl::StatusOr<std::pair<ClusterImplBaseSharedPtr, ThreadAwareLoadBalancerPtr>>
162
  createClusterImpl(const envoy::config::cluster::v3::Cluster& cluster,
163
385
                    ClusterFactoryContext& context) override {
164
385
    ProtobufTypes::MessagePtr config = createEmptyConfigProto();
165
385
    RETURN_IF_NOT_OK(Config::Utility::translateOpaqueConfig(
166
385
        cluster.cluster_type().typed_config(), context.messageValidationVisitor(), *config));
167
385
    return createClusterWithConfig(cluster,
168
385
                                   MessageUtil::downcastAndValidate<const ConfigProto&>(
169
385
                                       *config, context.messageValidationVisitor()),
170
385
                                   context);
171
385
  }
172

            
173
  virtual absl::StatusOr<std::pair<ClusterImplBaseSharedPtr, ThreadAwareLoadBalancerPtr>>
174
  createClusterWithConfig(const envoy::config::cluster::v3::Cluster& cluster,
175
                          const ConfigProto& proto_config, ClusterFactoryContext& context) PURE;
176
};
177

            
178
} // namespace Upstream
179
} // namespace Envoy