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