Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/extensions/clusters/eds/leds.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/extensions/clusters/eds/leds.h"
2
3
#include "envoy/common/exception.h"
4
#include "envoy/config/core/v3/config_source.pb.h"
5
6
#include "source/common/common/assert.h"
7
#include "source/common/config/decoded_resource_impl.h"
8
#include "source/common/config/xds_resource.h"
9
10
namespace Envoy {
11
namespace Upstream {
12
13
LedsSubscription::LedsSubscription(
14
    const envoy::config::endpoint::v3::LedsClusterLocalityConfig& leds_config,
15
    const std::string& cluster_name,
16
    Server::Configuration::TransportSocketFactoryContext& factory_context,
17
    Stats::Scope& cluster_stats_scope, const UpdateCb& callback)
18
    : Envoy::Config::SubscriptionBase<envoy::config::endpoint::v3::LbEndpoint>(
19
          factory_context.messageValidationVisitor(), leds_config.leds_collection_name()),
20
      local_info_(factory_context.serverFactoryContext().localInfo()), cluster_name_(cluster_name),
21
      stats_scope_(cluster_stats_scope.createScope("leds.")),
22
0
      stats_({ALL_LEDS_STATS(POOL_COUNTER(*stats_scope_))}), callback_(callback) {
23
0
  const xds::core::v3::ResourceLocator leds_resource_locator = THROW_OR_RETURN_VALUE(
24
0
      Config::XdsResourceIdentifier::decodeUrl(leds_config.leds_collection_name()),
25
0
      xds::core::v3::ResourceLocator);
26
0
  const auto resource_name = getResourceName();
27
0
  subscription_ = THROW_OR_RETURN_VALUE(
28
0
      factory_context.clusterManager().subscriptionFactory().collectionSubscriptionFromUrl(
29
0
          leds_resource_locator, leds_config.leds_config(), resource_name, *stats_scope_, *this,
30
0
          resource_decoder_),
31
0
      Config::SubscriptionPtr);
32
0
  subscription_->start({});
33
0
}
34
35
absl::Status
36
LedsSubscription::onConfigUpdate(const std::vector<Config::DecodedResourceRef>& added_resources,
37
                                 const Protobuf::RepeatedPtrField<std::string>& removed_resources,
38
0
                                 const std::string&) {
39
  // At least one resource must be added or removed.
40
0
  if (added_resources.empty() && removed_resources.empty()) {
41
0
    ENVOY_LOG(debug, "No added or removed LbEndpoint entries for cluster {} in onConfigUpdate()",
42
0
              cluster_name_);
43
0
    stats_.update_empty_.inc();
44
    // If it's the first update, and it has no resources, set the locality as active,
45
    // and update whoever is waiting for it, to allow the system to initialize.
46
0
    if (!initial_update_attempt_complete_) {
47
0
      initial_update_attempt_complete_ = true;
48
0
      callback_();
49
0
    }
50
0
    return absl::OkStatus();
51
0
  }
52
53
0
  ENVOY_LOG(info, "{}: add {} endpoint(s), remove {} endpoints(s)", cluster_name_,
54
0
            added_resources.size(), removed_resources.size());
55
56
  // Update the internal host list with the removed hosts.
57
0
  for (const auto& removed_resource_name : removed_resources) {
58
    // Remove the entry from the endpoints list.
59
0
    ENVOY_LOG(debug, "Removing endpoint {} using LEDS update.", removed_resource_name);
60
0
    endpoints_map_.erase(removed_resource_name);
61
0
  }
62
63
  // Update the internal host list with the added hosts.
64
0
  for (const auto& added_resource : added_resources) {
65
0
    const auto& added_resource_name = added_resource.get().name();
66
0
    ENVOY_LOG(trace, "Adding/Updating endpoint {} using LEDS update.", added_resource_name);
67
0
    envoy::config::endpoint::v3::LbEndpoint lb_endpoint =
68
0
        dynamic_cast<const envoy::config::endpoint::v3::LbEndpoint&>(
69
0
            added_resource.get().resource());
70
0
    endpoints_map_[added_resource_name] = std::move(lb_endpoint);
71
0
  }
72
73
  // Notify the callbacks that the host list has been modified.
74
0
  initial_update_attempt_complete_ = true;
75
0
  callback_();
76
0
  return absl::OkStatus();
77
0
}
78
79
void LedsSubscription::onConfigUpdateFailed(Envoy::Config::ConfigUpdateFailureReason reason,
80
0
                                            const EnvoyException*) {
81
0
  ASSERT(Envoy::Config::ConfigUpdateFailureReason::ConnectionFailure != reason);
82
0
  ENVOY_LOG(debug, "LEDS update failed");
83
84
  // Similar to EDS, we need to let the system initialize. Set the locality as
85
  // active, and update whoever is waiting for it.
86
0
  initial_update_attempt_complete_ = true;
87
0
  callback_();
88
0
}
89
90
} // namespace Upstream
91
} // namespace Envoy