Coverage Report

Created: 2024-09-19 09:45

/proc/self/cwd/source/common/router/vhds.cc
Line
Count
Source (jump to first uncovered line)
1
#include "source/common/router/vhds.h"
2
3
#include <chrono>
4
#include <cstdint>
5
#include <memory>
6
#include <string>
7
8
#include "envoy/config/core/v3/config_source.pb.h"
9
#include "envoy/config/subscription.h"
10
#include "envoy/service/discovery/v3/discovery.pb.h"
11
12
#include "source/common/common/assert.h"
13
#include "source/common/common/fmt.h"
14
#include "source/common/config/api_version.h"
15
#include "source/common/config/utility.h"
16
#include "source/common/grpc/common.h"
17
#include "source/common/protobuf/utility.h"
18
#include "source/common/router/config_impl.h"
19
20
namespace Envoy {
21
namespace Router {
22
23
absl::StatusOr<VhdsSubscriptionPtr> VhdsSubscription::createVhdsSubscription(
24
    RouteConfigUpdatePtr& config_update_info,
25
    Server::Configuration::ServerFactoryContext& factory_context, const std::string& stat_prefix,
26
0
    Rds::RouteConfigProvider* route_config_provider) {
27
0
  const auto& config_source = config_update_info->protobufConfigurationCast()
28
0
                                  .vhds()
29
0
                                  .config_source()
30
0
                                  .api_config_source()
31
0
                                  .api_type();
32
0
  if (config_source != envoy::config::core::v3::ApiConfigSource::DELTA_GRPC) {
33
0
    return absl::InvalidArgumentError("vhds: only 'DELTA_GRPC' is supported as an api_type.");
34
0
  }
35
36
0
  return std::unique_ptr<VhdsSubscription>(new VhdsSubscription(
37
0
      config_update_info, factory_context, stat_prefix, route_config_provider));
38
0
}
39
40
// Implements callbacks to handle DeltaDiscovery protocol for VirtualHostDiscoveryService
41
VhdsSubscription::VhdsSubscription(RouteConfigUpdatePtr& config_update_info,
42
                                   Server::Configuration::ServerFactoryContext& factory_context,
43
                                   const std::string& stat_prefix,
44
                                   Rds::RouteConfigProvider* route_config_provider)
45
    : Envoy::Config::SubscriptionBase<envoy::config::route::v3::VirtualHost>(
46
          factory_context.messageValidationContext().dynamicValidationVisitor(), "name"),
47
      config_update_info_(config_update_info),
48
      scope_(factory_context.scope().createScope(
49
          stat_prefix + "vhds." + config_update_info_->protobufConfigurationCast().name() + ".")),
50
      stats_({ALL_VHDS_STATS(POOL_COUNTER(*scope_))}),
51
      init_target_(fmt::format("VhdsConfigSubscription {}",
52
                               config_update_info_->protobufConfigurationCast().name()),
53
0
                   [this]() {
54
0
                     subscription_->start(
55
0
                         {config_update_info_->protobufConfigurationCast().name()});
56
0
                   }),
57
0
      route_config_provider_(route_config_provider) {
58
0
  const auto resource_name = getResourceName();
59
0
  Envoy::Config::SubscriptionOptions options;
60
0
  options.use_namespace_matching_ = true;
61
0
  subscription_ = THROW_OR_RETURN_VALUE(
62
0
      factory_context.clusterManager().subscriptionFactory().subscriptionFromConfigSource(
63
0
          config_update_info_->protobufConfigurationCast().vhds().config_source(),
64
0
          Grpc::Common::typeUrl(resource_name), *scope_, *this, resource_decoder_, options),
65
0
      Envoy::Config::SubscriptionPtr);
66
0
}
67
68
0
void VhdsSubscription::updateOnDemand(const std::string& with_route_config_name_prefix) {
69
0
  subscription_->requestOnDemandUpdate({with_route_config_name_prefix});
70
0
}
71
72
void VhdsSubscription::onConfigUpdateFailed(Envoy::Config::ConfigUpdateFailureReason reason,
73
0
                                            const EnvoyException*) {
74
0
  ASSERT(Envoy::Config::ConfigUpdateFailureReason::ConnectionFailure != reason);
75
  // We need to allow server startup to continue, even if we have a bad
76
  // config.
77
0
  init_target_.ready();
78
0
}
79
80
absl::Status VhdsSubscription::onConfigUpdate(
81
    const std::vector<Envoy::Config::DecodedResourceRef>& added_resources,
82
    const Protobuf::RepeatedPtrField<std::string>& removed_resources,
83
0
    const std::string& version_info) {
84
0
  RouteConfigUpdateReceiver::VirtualHostRefVector added_vhosts;
85
0
  std::set<std::string> added_resource_ids;
86
0
  for (const auto& resource : added_resources) {
87
0
    added_resource_ids.emplace(resource.get().name());
88
0
    std::copy(resource.get().aliases().begin(), resource.get().aliases().end(),
89
0
              std::inserter(added_resource_ids, added_resource_ids.end()));
90
    // the management server returns empty resources (they contain no virtual hosts in this case)
91
    // for aliases that it couldn't resolve.
92
0
    if (!resource.get().hasResource()) {
93
0
      continue;
94
0
    }
95
0
    added_vhosts.emplace_back(
96
0
        dynamic_cast<const envoy::config::route::v3::VirtualHost&>(resource.get().resource()));
97
0
  }
98
0
  if (config_update_info_->onVhdsUpdate(added_vhosts, added_resource_ids, removed_resources,
99
0
                                        version_info)) {
100
0
    stats_.config_reload_.inc();
101
0
    ENVOY_LOG(debug, "vhds: loading new configuration: config_name={} hash={}",
102
0
              config_update_info_->protobufConfigurationCast().name(),
103
0
              config_update_info_->configHash());
104
0
    if (route_config_provider_ != nullptr) {
105
0
      RETURN_IF_NOT_OK(route_config_provider_->onConfigUpdate());
106
0
    }
107
0
  }
108
109
0
  init_target_.ready();
110
0
  return absl::OkStatus();
111
0
}
112
113
} // namespace Router
114
} // namespace Envoy