LCOV - code coverage report
Current view: top level - source/common/rds - rds_route_config_subscription.cc (source / functions) Hit Total Coverage
Test: coverage.dat Lines: 46 73 63.0 %
Date: 2024-01-05 06:35:25 Functions: 7 8 87.5 %

          Line data    Source code
       1             : #include "source/common/rds/rds_route_config_subscription.h"
       2             : 
       3             : #include "source/common/common/logger.h"
       4             : #include "source/common/rds/util.h"
       5             : 
       6             : namespace Envoy {
       7             : namespace Rds {
       8             : 
       9             : RdsRouteConfigSubscription::RdsRouteConfigSubscription(
      10             :     RouteConfigUpdatePtr&& config_update,
      11             :     Envoy::Config::OpaqueResourceDecoderSharedPtr&& resource_decoder,
      12             :     const envoy::config::core::v3::ConfigSource& config_source,
      13             :     const std::string& route_config_name, const uint64_t manager_identifier,
      14             :     Server::Configuration::ServerFactoryContext& factory_context, const std::string& stat_prefix,
      15             :     const std::string& rds_type, RouteConfigProviderManager& route_config_provider_manager)
      16             :     : route_config_name_(route_config_name),
      17             :       scope_(factory_context.scope().createScope(stat_prefix + route_config_name_ + ".")),
      18             :       factory_context_(factory_context),
      19             :       parent_init_target_(
      20             :           fmt::format("RdsRouteConfigSubscription {} init {}", rds_type, route_config_name_),
      21          50 :           [this]() { local_init_manager_.initialize(local_init_watcher_); }),
      22             :       local_init_watcher_(fmt::format("{} local-init-watcher {}", rds_type, route_config_name_),
      23          50 :                           [this]() { parent_init_target_.ready(); }),
      24             :       local_init_target_(fmt::format("RdsRouteConfigSubscription {} local-init-target {}", rds_type,
      25             :                                      route_config_name_),
      26          50 :                          [this]() { subscription_->start({route_config_name_}); }),
      27             :       local_init_manager_(fmt::format("{} local-init-manager {}", rds_type, route_config_name_)),
      28             :       stat_prefix_(stat_prefix), rds_type_(rds_type),
      29             :       stats_({ALL_RDS_STATS(POOL_COUNTER(*scope_), POOL_GAUGE(*scope_))}),
      30             :       route_config_provider_manager_(route_config_provider_manager),
      31             :       manager_identifier_(manager_identifier), config_update_info_(std::move(config_update)),
      32          50 :       resource_decoder_(std::move(resource_decoder)) {
      33          50 :   const auto resource_type = route_config_provider_manager_.protoTraits().resourceType();
      34          50 :   subscription_ =
      35          50 :       factory_context.clusterManager().subscriptionFactory().subscriptionFromConfigSource(
      36          50 :           config_source, Envoy::Grpc::Common::typeUrl(resource_type), *scope_, *this,
      37          50 :           resource_decoder_, {});
      38          50 :   local_init_manager_.add(local_init_target_);
      39          50 : }
      40             : 
      41          50 : RdsRouteConfigSubscription::~RdsRouteConfigSubscription() {
      42             :   // If we get destroyed during initialization, make sure we signal that we "initialized".
      43          50 :   local_init_target_.ready();
      44             : 
      45             :   // The ownership of RdsRouteConfigProviderImpl is shared among all HttpConnectionManagers that
      46             :   // hold a shared_ptr to it. The RouteConfigProviderManager holds weak_ptrs to the
      47             :   // RdsRouteConfigProviders. Therefore, the map entry for the RdsRouteConfigProvider has to get
      48             :   // cleaned by the RdsRouteConfigProvider's destructor.
      49          50 :   route_config_provider_manager_.eraseDynamicProvider(manager_identifier_);
      50          50 : }
      51             : 
      52             : absl::Status RdsRouteConfigSubscription::onConfigUpdate(
      53             :     const std::vector<Envoy::Config::DecodedResourceRef>& resources,
      54         100 :     const std::string& version_info) {
      55         100 :   if (resources.empty()) {
      56           0 :     ENVOY_LOG(debug, "Missing {} RouteConfiguration for {} in onConfigUpdate()", rds_type_,
      57           0 :               route_config_name_);
      58           0 :     stats_.update_empty_.inc();
      59           0 :     local_init_target_.ready();
      60           0 :     return absl::OkStatus();
      61           0 :   }
      62         100 :   if (resources.size() != 1) {
      63           0 :     return absl::InvalidArgumentError(
      64           0 :         fmt::format("Unexpected {} resource length: {}", rds_type_, resources.size()));
      65           0 :   }
      66             : 
      67         100 :   const auto& route_config = resources[0].get().resource();
      68         100 :   Protobuf::ReflectableMessage reflectable_config = createReflectableMessage(route_config);
      69         100 :   if (reflectable_config->GetDescriptor()->full_name() !=
      70         100 :       route_config_provider_manager_.protoTraits().resourceType()) {
      71           0 :     return absl::InvalidArgumentError(
      72           0 :         fmt::format("Unexpected {} configuration type (expecting {}): {}", rds_type_,
      73           0 :                     route_config_provider_manager_.protoTraits().resourceType(),
      74           0 :                     reflectable_config->GetDescriptor()->full_name()));
      75           0 :   }
      76         100 :   if (resourceName(route_config_provider_manager_.protoTraits(), route_config) !=
      77         100 :       route_config_name_) {
      78           0 :     return absl::InvalidArgumentError(
      79           0 :         fmt::format("Unexpected {} configuration (expecting {}): {}", rds_type_, route_config_name_,
      80           0 :                     resourceName(route_config_provider_manager_.protoTraits(), route_config)));
      81           0 :   }
      82         100 :   std::unique_ptr<Init::ManagerImpl> noop_init_manager;
      83         100 :   std::unique_ptr<Cleanup> resume_rds;
      84         100 :   if (config_update_info_->onRdsUpdate(route_config, version_info)) {
      85          36 :     stats_.config_reload_.inc();
      86          36 :     stats_.config_reload_time_ms_.set(DateUtil::nowToMilliseconds(factory_context_.timeSource()));
      87             : 
      88          36 :     beforeProviderUpdate(noop_init_manager, resume_rds);
      89             : 
      90          36 :     ENVOY_LOG(debug, "rds: loading new configuration: config_name={} hash={}", route_config_name_,
      91          36 :               config_update_info_->configHash());
      92             : 
      93          36 :     if (route_config_provider_ != nullptr) {
      94          36 :       THROW_IF_NOT_OK(route_config_provider_->onConfigUpdate());
      95          36 :     }
      96             : 
      97          36 :     afterProviderUpdate();
      98          36 :   }
      99             : 
     100         100 :   local_init_target_.ready();
     101         100 :   return absl::OkStatus();
     102         100 : }
     103             : 
     104             : absl::Status RdsRouteConfigSubscription::onConfigUpdate(
     105             :     const std::vector<Envoy::Config::DecodedResourceRef>& added_resources,
     106          16 :     const Protobuf::RepeatedPtrField<std::string>& removed_resources, const std::string&) {
     107          16 :   if (!removed_resources.empty()) {
     108             :     // TODO(#2500) when on-demand resource loading is supported, an RDS removal may make sense
     109             :     // (see discussion in #6879), and so we should do something other than ignoring here.
     110           0 :     ENVOY_LOG(trace,
     111           0 :               "Server sent a delta {} update attempting to remove a resource (name: {}). Ignoring.",
     112           0 :               rds_type_, removed_resources[0]);
     113           0 :   }
     114          16 :   if (!added_resources.empty()) {
     115          16 :     return onConfigUpdate(added_resources, added_resources[0].get().version());
     116          16 :   }
     117           0 :   return absl::OkStatus();
     118          16 : }
     119             : 
     120             : void RdsRouteConfigSubscription::onConfigUpdateFailed(
     121           0 :     Envoy::Config::ConfigUpdateFailureReason reason, const EnvoyException*) {
     122           0 :   ASSERT(Envoy::Config::ConfigUpdateFailureReason::ConnectionFailure != reason);
     123             :   // We need to allow server startup to continue, even if we have a bad
     124             :   // config.
     125           0 :   local_init_target_.ready();
     126           0 : }
     127             : 
     128             : } // namespace Rds
     129             : } // namespace Envoy

Generated by: LCOV version 1.15