1
#pragma once
2

            
3
#include <chrono>
4
#include <cstdint>
5
#include <functional>
6
#include <string>
7

            
8
#include "envoy/config/cluster/v3/cluster.pb.h"
9
#include "envoy/config/endpoint/v3/endpoint.pb.h"
10
#include "envoy/config/endpoint/v3/endpoint_components.pb.h"
11
#include "envoy/extensions/clusters/dns/v3/dns_cluster.pb.h"
12
#include "envoy/extensions/clusters/dns/v3/dns_cluster.pb.validate.h"
13
#include "envoy/stats/scope.h"
14

            
15
#include "source/common/common/empty_string.h"
16
#include "source/common/upstream/cluster_factory_impl.h"
17
#include "source/common/upstream/upstream_impl.h"
18
#include "source/extensions/clusters/common/logical_host.h"
19

            
20
namespace Envoy {
21
namespace Upstream {
22

            
23
class LogicalDnsClusterFactory;
24
class LogicalDnsClusterTest;
25

            
26
/**
27
 * The LogicalDnsCluster is a type of cluster that creates a single logical host that wraps
28
 * an async DNS resolver. The DNS resolver will continuously resolve, and swap in the first IP
29
 * address in the resolution set. However the logical owning host will not change. Any created
30
 * connections against this host will use the currently resolved IP. This means that a connection
31
 * pool using the logical host may end up with connections to many different real IPs.
32
 *
33
 * This cluster type is useful for large web services that use DNS in a round robin fashion, such
34
 * that DNS resolution may repeatedly return different results. A single connection pool can be
35
 * created that will internally have connections to different backends, while still allowing long
36
 * connection lengths and keep alive. The cluster type should only be used when an IP address change
37
 * means that connections using the IP should not drain.
38
 */
39
class LogicalDnsCluster : public ClusterImplBase {
40
public:
41
  ~LogicalDnsCluster() override;
42

            
43
  // Upstream::Cluster
44
154
  InitializePhase initializePhase() const override { return InitializePhase::Primary; }
45

            
46
  static absl::StatusOr<std::unique_ptr<LogicalDnsCluster>>
47
  create(const envoy::config::cluster::v3::Cluster& cluster,
48
         const envoy::extensions::clusters::dns::v3::DnsCluster& dns_cluster,
49
         ClusterFactoryContext& context, Network::DnsResolverSharedPtr dns_resolver);
50

            
51
protected:
52
  LogicalDnsCluster(const envoy::config::cluster::v3::Cluster& cluster,
53
                    const envoy::extensions::clusters::dns::v3::DnsCluster& dns_cluster,
54
                    ClusterFactoryContext& context, Network::DnsResolverSharedPtr dns_resolver,
55
                    absl::Status& creation_status);
56

            
57
private:
58
  friend class LogicalDnsClusterFactory;
59
  friend class LogicalDnsClusterTest;
60

            
61
649
  const envoy::config::endpoint::v3::LocalityLbEndpoints& localityLbEndpoint() const {
62
    // This is checked in the constructor, i.e. at config load time.
63
649
    ASSERT(load_assignment_.endpoints().size() == 1);
64
649
    return load_assignment_.endpoints()[0];
65
649
  }
66

            
67
485
  const envoy::config::endpoint::v3::LbEndpoint& lbEndpoint() const {
68
    // This is checked in the constructor, i.e. at config load time.
69
485
    ASSERT(localityLbEndpoint().lb_endpoints().size() == 1);
70
485
    return localityLbEndpoint().lb_endpoints()[0];
71
485
  }
72

            
73
  void startResolve();
74

            
75
  // ClusterImplBase
76
  void startPreInit() override;
77

            
78
  Network::DnsResolverSharedPtr dns_resolver_;
79
  const std::chrono::milliseconds dns_refresh_rate_ms_;
80
  const std::chrono::milliseconds dns_jitter_ms_;
81
  BackOffStrategyPtr failure_backoff_strategy_;
82
  const bool respect_dns_ttl_;
83
  Network::DnsLookupFamily dns_lookup_family_;
84
  Event::TimerPtr resolve_timer_;
85
  std::string dns_address_;
86
  uint32_t dns_port_;
87
  std::string hostname_;
88
  Network::Address::InstanceConstSharedPtr current_resolved_address_;
89
  std::vector<Network::Address::InstanceConstSharedPtr> current_resolved_address_list_;
90
  LogicalHostSharedPtr logical_host_;
91
  Network::ActiveDnsQuery* active_dns_query_{};
92
  const LocalInfo::LocalInfo& local_info_;
93
  const envoy::config::endpoint::v3::ClusterLoadAssignment load_assignment_;
94
};
95

            
96
} // namespace Upstream
97
} // namespace Envoy