Line data Source code
1 : #include "source/common/upstream/cluster_factory_impl.h" 2 : 3 : #include "envoy/config/cluster/v3/cluster.pb.h" 4 : #include "envoy/server/options.h" 5 : 6 : #include "source/common/http/utility.h" 7 : #include "source/common/network/address_impl.h" 8 : #include "source/common/network/dns_resolver/dns_factory_util.h" 9 : #include "source/common/network/resolver_impl.h" 10 : #include "source/common/network/socket_option_factory.h" 11 : #include "source/common/upstream/health_checker_impl.h" 12 : #include "source/server/transport_socket_config_impl.h" 13 : 14 : namespace Envoy { 15 : namespace Upstream { 16 : 17 : absl::StatusOr<std::pair<ClusterSharedPtr, ThreadAwareLoadBalancerPtr>> 18 : ClusterFactoryImplBase::create(const envoy::config::cluster::v3::Cluster& cluster, 19 : Server::Configuration::ServerFactoryContext& server_context, 20 : ClusterManager& cm, LazyCreateDnsResolver dns_resolver_fn, 21 : Ssl::ContextManager& ssl_context_manager, 22 : Outlier::EventLoggerSharedPtr outlier_event_logger, 23 159 : bool added_via_api) { 24 159 : std::string cluster_type; 25 : 26 159 : if (!cluster.has_cluster_type()) { 27 159 : switch (cluster.type()) { 28 0 : PANIC_ON_PROTO_ENUM_SENTINEL_VALUES; 29 131 : case envoy::config::cluster::v3::Cluster::STATIC: 30 131 : cluster_type = "envoy.cluster.static"; 31 131 : break; 32 0 : case envoy::config::cluster::v3::Cluster::STRICT_DNS: 33 0 : cluster_type = "envoy.cluster.strict_dns"; 34 0 : break; 35 0 : case envoy::config::cluster::v3::Cluster::LOGICAL_DNS: 36 0 : cluster_type = "envoy.cluster.logical_dns"; 37 0 : break; 38 0 : case envoy::config::cluster::v3::Cluster::ORIGINAL_DST: 39 0 : cluster_type = "envoy.cluster.original_dst"; 40 0 : break; 41 28 : case envoy::config::cluster::v3::Cluster::EDS: 42 28 : cluster_type = "envoy.cluster.eds"; 43 28 : break; 44 159 : } 45 159 : } else { 46 0 : cluster_type = cluster.cluster_type().name(); 47 0 : } 48 : 49 159 : if (cluster.common_lb_config().has_consistent_hashing_lb_config() && 50 159 : cluster.common_lb_config().consistent_hashing_lb_config().use_hostname_for_hashing() && 51 159 : cluster.type() != envoy::config::cluster::v3::Cluster::STRICT_DNS) { 52 0 : return absl::InvalidArgumentError(fmt::format( 53 0 : "Cannot use hostname for consistent hashing loadbalancing for cluster of type: '{}'", 54 0 : cluster_type)); 55 0 : } 56 159 : ClusterFactory* factory = Registry::FactoryRegistry<ClusterFactory>::getFactory(cluster_type); 57 : 58 159 : if (factory == nullptr) { 59 0 : return absl::InvalidArgumentError(fmt::format( 60 0 : "Didn't find a registered cluster factory implementation for name: '{}'", cluster_type)); 61 0 : } 62 : 63 159 : ClusterFactoryContextImpl context(server_context, cm, dns_resolver_fn, ssl_context_manager, 64 159 : std::move(outlier_event_logger), added_via_api); 65 159 : return factory->create(cluster, context); 66 159 : } 67 : 68 : Network::DnsResolverSharedPtr 69 : ClusterFactoryImplBase::selectDnsResolver(const envoy::config::cluster::v3::Cluster& cluster, 70 0 : ClusterFactoryContext& context) { 71 : // We make this a shared pointer to deal with the distinct ownership 72 : // scenarios that can exist: in one case, we pass in the "default" 73 : // DNS resolver that is owned by the Server::Instance. In the case 74 : // where 'dns_resolvers' is specified, we have per-cluster DNS 75 : // resolvers that are created here but ownership resides with 76 : // StrictDnsClusterImpl/LogicalDnsCluster. 77 0 : if ((cluster.has_typed_dns_resolver_config() && 78 0 : !(cluster.typed_dns_resolver_config().typed_config().type_url().empty())) || 79 0 : (cluster.has_dns_resolution_config() && 80 0 : !cluster.dns_resolution_config().resolvers().empty()) || 81 0 : !cluster.dns_resolvers().empty()) { 82 : 83 0 : envoy::config::core::v3::TypedExtensionConfig typed_dns_resolver_config; 84 0 : Network::DnsResolverFactory& dns_resolver_factory = 85 0 : Network::createDnsResolverFactoryFromProto(cluster, typed_dns_resolver_config); 86 0 : auto& server_context = context.serverFactoryContext(); 87 0 : return dns_resolver_factory.createDnsResolver(server_context.mainThreadDispatcher(), 88 0 : server_context.api(), typed_dns_resolver_config); 89 0 : } 90 : 91 0 : return context.dnsResolver(); 92 0 : } 93 : 94 : absl::StatusOr<std::pair<ClusterSharedPtr, ThreadAwareLoadBalancerPtr>> 95 : ClusterFactoryImplBase::create(const envoy::config::cluster::v3::Cluster& cluster, 96 159 : ClusterFactoryContext& context) { 97 : 98 159 : absl::StatusOr<std::pair<ClusterImplBaseSharedPtr, ThreadAwareLoadBalancerPtr>> 99 159 : status_or_cluster = createClusterImpl(cluster, context); 100 159 : RETURN_IF_STATUS_NOT_OK(status_or_cluster); 101 159 : std::pair<ClusterImplBaseSharedPtr, ThreadAwareLoadBalancerPtr>& new_cluster_pair = 102 159 : status_or_cluster.value(); 103 : 104 159 : auto& server_context = context.serverFactoryContext(); 105 : 106 159 : if (!cluster.health_checks().empty()) { 107 : // TODO(htuch): Need to support multiple health checks in v2. 108 0 : if (cluster.health_checks().size() != 1) { 109 0 : return absl::InvalidArgumentError("Multiple health checks not supported"); 110 0 : } else { 111 0 : auto checker_or_error = HealthCheckerFactory::create(cluster.health_checks()[0], 112 0 : *new_cluster_pair.first, server_context); 113 0 : RETURN_IF_STATUS_NOT_OK(checker_or_error); 114 0 : new_cluster_pair.first->setHealthChecker(checker_or_error.value()); 115 0 : } 116 0 : } 117 : 118 159 : auto detector_or_error = Outlier::DetectorImplFactory::createForCluster( 119 159 : *new_cluster_pair.first, cluster, server_context.mainThreadDispatcher(), 120 159 : server_context.runtime(), context.outlierEventLogger(), 121 159 : server_context.api().randomGenerator()); 122 159 : RETURN_IF_STATUS_NOT_OK(detector_or_error); 123 159 : new_cluster_pair.first->setOutlierDetector(detector_or_error.value()); 124 : 125 159 : return status_or_cluster; 126 159 : } 127 : 128 : } // namespace Upstream 129 : } // namespace Envoy