Line data Source code
1 : #include "source/common/router/route_config_update_receiver_impl.h" 2 : 3 : #include <string> 4 : #include <utility> 5 : 6 : #include "envoy/config/route/v3/route.pb.h" 7 : #include "envoy/service/discovery/v3/discovery.pb.h" 8 : 9 : #include "source/common/common/assert.h" 10 : #include "source/common/common/fmt.h" 11 : #include "source/common/common/thread.h" 12 : #include "source/common/config/resource_name.h" 13 : #include "source/common/protobuf/utility.h" 14 : #include "source/common/router/config_impl.h" 15 : 16 : namespace Envoy { 17 : namespace Router { 18 : 19 : namespace { 20 : 21 : // Resets 'route_config::virtual_hosts' by merging VirtualHost contained in 22 : // 'rds_vhosts' and 'vhds_vhosts'. 23 : void rebuildRouteConfigVirtualHosts( 24 : const RouteConfigUpdateReceiverImpl::VirtualHostMap& rds_vhosts, 25 : const RouteConfigUpdateReceiverImpl::VirtualHostMap& vhds_vhosts, 26 0 : envoy::config::route::v3::RouteConfiguration& route_config) { 27 0 : route_config.clear_virtual_hosts(); 28 0 : for (const auto& vhost : rds_vhosts) { 29 0 : route_config.mutable_virtual_hosts()->Add()->CheckTypeAndMergeFrom(vhost.second); 30 0 : } 31 0 : for (const auto& vhost : vhds_vhosts) { 32 0 : route_config.mutable_virtual_hosts()->Add()->CheckTypeAndMergeFrom(vhost.second); 33 0 : } 34 0 : } 35 : 36 : } // namespace 37 : 38 50 : Rds::ConfigConstSharedPtr ConfigTraitsImpl::createNullConfig() const { 39 50 : return std::make_shared<NullConfigImpl>(); 40 50 : } 41 : 42 : Rds::ConfigConstSharedPtr 43 : ConfigTraitsImpl::createConfig(const Protobuf::Message& rc, 44 : Server::Configuration::ServerFactoryContext& factory_context, 45 110 : bool validate_clusters_default) const { 46 110 : ASSERT(dynamic_cast<const envoy::config::route::v3::RouteConfiguration*>(&rc)); 47 110 : return std::make_shared<ConfigImpl>( 48 110 : static_cast<const envoy::config::route::v3::RouteConfiguration&>(rc), factory_context, 49 110 : validator_, validate_clusters_default); 50 110 : } 51 : 52 : bool RouteConfigUpdateReceiverImpl::onRdsUpdate(const Protobuf::Message& rc, 53 100 : const std::string& version_info) { 54 100 : uint64_t new_hash = base_.getHash(rc); 55 100 : if (!base_.checkHash(new_hash)) { 56 64 : return false; 57 64 : } 58 36 : auto new_route_config = std::make_unique<envoy::config::route::v3::RouteConfiguration>(); 59 36 : new_route_config->CheckTypeAndMergeFrom(rc); 60 36 : const uint64_t new_vhds_config_hash = 61 36 : new_route_config->has_vhds() ? MessageUtil::hash(new_route_config->vhds()) : 0ul; 62 36 : if (new_route_config->has_vhds()) { 63 : // When using VHDS, stash away RDS vhosts, so that they can be merged with VHDS vhosts in 64 : // onVhdsUpdate. 65 0 : if (rds_virtual_hosts_ == nullptr) { 66 0 : rds_virtual_hosts_ = std::make_unique<VirtualHostMap>(); 67 0 : } else { 68 0 : rds_virtual_hosts_->clear(); 69 0 : } 70 0 : for (const auto& vhost : new_route_config->virtual_hosts()) { 71 0 : rds_virtual_hosts_->emplace(vhost.name(), vhost); 72 0 : } 73 0 : if (vhds_virtual_hosts_ != nullptr && !vhds_virtual_hosts_->empty()) { 74 : // If there are vhosts supplied by VHDS, merge them with RDS vhosts. 75 0 : rebuildRouteConfigVirtualHosts(*rds_virtual_hosts_, *vhds_virtual_hosts_, *new_route_config); 76 0 : } 77 0 : } 78 36 : base_.updateConfig(std::move(new_route_config)); 79 36 : base_.updateHash(new_hash); 80 36 : vhds_configuration_changed_ = new_vhds_config_hash != last_vhds_config_hash_; 81 36 : last_vhds_config_hash_ = new_vhds_config_hash; 82 : 83 36 : base_.onUpdateCommon(version_info); 84 36 : return true; 85 100 : } 86 : 87 : bool RouteConfigUpdateReceiverImpl::onVhdsUpdate( 88 : const VirtualHostRefVector& added_vhosts, const std::set<std::string>& added_resource_ids, 89 : const Protobuf::RepeatedPtrField<std::string>& removed_resources, 90 0 : const std::string& version_info) { 91 0 : std::unique_ptr<VirtualHostMap> vhosts_after_this_update; 92 0 : if (vhds_virtual_hosts_ != nullptr) { 93 0 : vhosts_after_this_update = std::make_unique<VirtualHostMap>(*vhds_virtual_hosts_); 94 0 : } else { 95 0 : vhosts_after_this_update = std::make_unique<VirtualHostMap>(); 96 0 : } 97 0 : if (rds_virtual_hosts_ == nullptr) { 98 0 : rds_virtual_hosts_ = std::make_unique<VirtualHostMap>(); 99 0 : } 100 0 : const bool removed = removeVhosts(*vhosts_after_this_update, removed_resources); 101 0 : const bool updated = updateVhosts(*vhosts_after_this_update, added_vhosts); 102 : 103 0 : auto route_config_after_this_update = 104 0 : std::make_unique<envoy::config::route::v3::RouteConfiguration>(); 105 0 : route_config_after_this_update->CheckTypeAndMergeFrom(base_.protobufConfiguration()); 106 0 : rebuildRouteConfigVirtualHosts(*rds_virtual_hosts_, *vhosts_after_this_update, 107 0 : *route_config_after_this_update); 108 : 109 0 : base_.updateConfig(std::move(route_config_after_this_update)); 110 : // No exception, route_config_after_this_update is valid, can update the state. 111 0 : vhds_virtual_hosts_ = std::move(vhosts_after_this_update); 112 0 : resource_ids_in_last_update_ = added_resource_ids; 113 0 : base_.onUpdateCommon(version_info); 114 : 115 0 : return removed || updated || !resource_ids_in_last_update_.empty(); 116 0 : } 117 : 118 : bool RouteConfigUpdateReceiverImpl::removeVhosts( 119 0 : VirtualHostMap& vhosts, const Protobuf::RepeatedPtrField<std::string>& removed_vhost_names) { 120 0 : bool vhosts_removed = false; 121 0 : for (const auto& vhost_name : removed_vhost_names) { 122 0 : auto found = vhosts.find(vhost_name); 123 0 : if (found != vhosts.end()) { 124 0 : vhosts_removed = true; 125 0 : vhosts.erase(vhost_name); 126 0 : } 127 0 : } 128 0 : return vhosts_removed; 129 0 : } 130 : 131 : bool RouteConfigUpdateReceiverImpl::updateVhosts(VirtualHostMap& vhosts, 132 0 : const VirtualHostRefVector& added_vhosts) { 133 0 : bool vhosts_added = false; 134 0 : for (const auto& vhost : added_vhosts) { 135 0 : auto found = vhosts.find(vhost.get().name()); 136 0 : if (found != vhosts.end()) { 137 0 : vhosts.erase(found); 138 0 : } 139 0 : vhosts.emplace(vhost.get().name(), vhost.get()); 140 0 : vhosts_added = true; 141 0 : } 142 0 : return vhosts_added; 143 0 : } 144 : 145 : } // namespace Router 146 : } // namespace Envoy