-
Notifications
You must be signed in to change notification settings - Fork 4.8k
/
cds_api_impl.cc
93 lines (83 loc) · 4.07 KB
/
cds_api_impl.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include "source/common/upstream/cds_api_impl.h"
#include "source/common/common/assert.h"
#include "source/common/grpc/common.h"
#include "absl/strings/str_join.h"
namespace Envoy {
namespace Upstream {
CdsApiPtr CdsApiImpl::create(const envoy::config::core::v3::ConfigSource& cds_config,
const xds::core::v3::ResourceLocator* cds_resources_locator,
ClusterManager& cm, Stats::Scope& scope,
ProtobufMessage::ValidationVisitor& validation_visitor) {
return CdsApiPtr{
new CdsApiImpl(cds_config, cds_resources_locator, cm, scope, validation_visitor)};
}
CdsApiImpl::CdsApiImpl(const envoy::config::core::v3::ConfigSource& cds_config,
const xds::core::v3::ResourceLocator* cds_resources_locator,
ClusterManager& cm, Stats::Scope& scope,
ProtobufMessage::ValidationVisitor& validation_visitor)
: Envoy::Config::SubscriptionBase<envoy::config::cluster::v3::Cluster>(validation_visitor,
"name"),
helper_(cm, "cds"), cm_(cm), scope_(scope.createScope("cluster_manager.cds.")) {
const auto resource_name = getResourceName();
if (cds_resources_locator == nullptr) {
subscription_ = THROW_OR_RETURN_VALUE(cm_.subscriptionFactory().subscriptionFromConfigSource(
cds_config, Grpc::Common::typeUrl(resource_name),
*scope_, *this, resource_decoder_, {}),
Config::SubscriptionPtr);
} else {
subscription_ = THROW_OR_RETURN_VALUE(
cm.subscriptionFactory().collectionSubscriptionFromUrl(
*cds_resources_locator, cds_config, resource_name, *scope_, *this, resource_decoder_),
Config::SubscriptionPtr);
}
}
absl::Status CdsApiImpl::onConfigUpdate(const std::vector<Config::DecodedResourceRef>& resources,
const std::string& version_info) {
auto all_existing_clusters = cm_.clusters();
// Exclude the clusters which CDS wants to add.
for (const auto& resource : resources) {
all_existing_clusters.active_clusters_.erase(resource.get().name());
all_existing_clusters.warming_clusters_.erase(resource.get().name());
}
Protobuf::RepeatedPtrField<std::string> to_remove_repeated;
for (const auto& [cluster_name, _] : all_existing_clusters.active_clusters_) {
UNREFERENCED_PARAMETER(_);
*to_remove_repeated.Add() = cluster_name;
}
for (const auto& [cluster_name, _] : all_existing_clusters.warming_clusters_) {
UNREFERENCED_PARAMETER(_);
// Do not add the cluster twice when the cluster is both active and warming.
if (!all_existing_clusters.active_clusters_.contains(cluster_name)) {
*to_remove_repeated.Add() = cluster_name;
}
}
return onConfigUpdate(resources, to_remove_repeated, version_info);
}
absl::Status
CdsApiImpl::onConfigUpdate(const std::vector<Config::DecodedResourceRef>& added_resources,
const Protobuf::RepeatedPtrField<std::string>& removed_resources,
const std::string& system_version_info) {
auto exception_msgs =
helper_.onConfigUpdate(added_resources, removed_resources, system_version_info);
runInitializeCallbackIfAny();
if (!exception_msgs.empty()) {
return absl::InvalidArgumentError(
fmt::format("Error adding/updating cluster(s) {}", absl::StrJoin(exception_msgs, ", ")));
}
return absl::OkStatus();
}
void CdsApiImpl::onConfigUpdateFailed(Envoy::Config::ConfigUpdateFailureReason reason,
const EnvoyException*) {
ASSERT(Envoy::Config::ConfigUpdateFailureReason::ConnectionFailure != reason);
// We need to allow server startup to continue, even if we have a bad
// config.
runInitializeCallbackIfAny();
}
void CdsApiImpl::runInitializeCallbackIfAny() {
if (initialize_callback_) {
initialize_callback_();
initialize_callback_ = nullptr;
}
}
} // namespace Upstream
} // namespace Envoy