@@ -747,6 +747,13 @@ class OdCdsXdstpIntegrationTest : public XdsTpConfigsIntegration {
747
747
return builder.listener ();
748
748
}
749
749
750
+ envoy::config::endpoint::v3::ClusterLoadAssignment
751
+ buildClusterLoadAssignment (const std::string& name, size_t upstream_idx) {
752
+ return ConfigHelper::buildClusterLoadAssignment (
753
+ name, Network::Test::getLoopbackAddressString (ipVersion ()),
754
+ fake_upstreams_[upstream_idx]->localAddress ()->ip ()->port ());
755
+ }
756
+
750
757
bool compareRequest (const std::string& type_url,
751
758
const std::vector<std::string>& expected_resource_subscriptions,
752
759
const std::vector<std::string>& expected_resource_unsubscriptions,
@@ -919,6 +926,72 @@ TEST_P(OdCdsXdstpIntegrationTest, OnDemandClusterDiscoveryAsksForNonexistentClus
919
926
cleanupUpstreamAndDownstream ();
920
927
}
921
928
929
+ // tests a scenario when:
930
+ // - making a request to an unknown cluster
931
+ // - odcds initiates a connection with a request for the cluster
932
+ // - a response contains an EDS cluster
933
+ // - an EDS request is sent to the same authority
934
+ // - an EDS response is received
935
+ // - request is resumed
936
+ TEST_P (OdCdsXdstpIntegrationTest, OnDemandCdsWithEds) {
937
+ initialize ();
938
+ codec_client_ = makeHttpConnection (makeClientConnection (lookupPort (" http" )));
939
+ const std::string cds_cluster_name =
940
+ " xdstp://authority1.com/envoy.config.cluster.v3.Cluster/on_demand_clusters/"
941
+ " new_cluster_with_eds" ;
942
+ const std::string eds_service_name =
943
+ " xdstp://authority1.com/envoy.config.endpoint.v3.ClusterLoadAssignment/on_demand_clusters/"
944
+ " new_cluster_with_eds" ;
945
+
946
+ envoy::config::cluster::v3::Cluster new_cluster_with_eds;
947
+ new_cluster_with_eds.set_name (cds_cluster_name);
948
+ new_cluster_with_eds.set_type (envoy::config::cluster::v3::Cluster::EDS);
949
+ auto * eds_cluster_config = new_cluster_with_eds.mutable_eds_cluster_config ();
950
+ eds_cluster_config->set_service_name (eds_service_name);
951
+ ConfigHelper::setHttp2 (new_cluster_with_eds);
952
+
953
+ Http::TestRequestHeaderMapImpl request_headers{{" :method" , " GET" },
954
+ {" :path" , " /" },
955
+ {" :scheme" , " http" },
956
+ {" :authority" , " vhost.first" },
957
+ {" Pick-This-Cluster" , cds_cluster_name}};
958
+ IntegrationStreamDecoderPtr response = codec_client_->makeHeaderOnlyRequest (request_headers);
959
+
960
+ // Authority1 should receive the ODCDS request.
961
+ EXPECT_TRUE (compareDiscoveryRequest (
962
+ Config::TestTypeUrl::get ().Cluster , " " , {cds_cluster_name}, {cds_cluster_name}, {}, true ,
963
+ Grpc::Status::WellKnownGrpcStatus::Ok, " " , authority1_xds_stream_.get ()));
964
+ sendDiscoveryResponse<envoy::config::cluster::v3::Cluster>(
965
+ Config::TestTypeUrl::get ().Cluster , {new_cluster_with_eds}, {new_cluster_with_eds}, {}, " 1" ,
966
+ {}, authority1_xds_stream_.get ());
967
+ // After the CDS response, Envoy will send an EDS request for the new cluster.
968
+ EXPECT_TRUE (compareDiscoveryRequest (
969
+ Config::TestTypeUrl::get ().ClusterLoadAssignment , " " , {eds_service_name}, {eds_service_name},
970
+ {}, false , Grpc::Status::WellKnownGrpcStatus::Ok, " " , authority1_xds_stream_.get ()));
971
+ sendDiscoveryResponse<envoy::config::endpoint::v3::ClusterLoadAssignment>(
972
+ Config::TestTypeUrl::get ().ClusterLoadAssignment ,
973
+ {buildClusterLoadAssignment (eds_service_name, new_cluster_upstream_idx_)},
974
+ {buildClusterLoadAssignment (eds_service_name, new_cluster_upstream_idx_)}, {}, " 2" , {},
975
+ authority1_xds_stream_.get ());
976
+ // Now, Envoy should ACK the original CDS response.
977
+ EXPECT_TRUE (compareDiscoveryRequest (Config::TestTypeUrl::get ().Cluster , " 1" , {cds_cluster_name},
978
+ {}, {}, false , Grpc::Status::WellKnownGrpcStatus::Ok, " " ,
979
+ authority1_xds_stream_.get ()));
980
+ // And finally, Envoy should ACK the EDS response.
981
+ EXPECT_TRUE (compareDiscoveryRequest (
982
+ Config::TestTypeUrl::get ().ClusterLoadAssignment , " 2" , {eds_service_name}, {}, {}, false ,
983
+ Grpc::Status::WellKnownGrpcStatus::Ok, " " , authority1_xds_stream_.get ()));
984
+
985
+ waitForNextUpstreamRequest (new_cluster_upstream_idx_);
986
+ // Send response headers, and end_stream if there is no response body.
987
+ upstream_request_->encodeHeaders (default_response_headers_, true );
988
+
989
+ ASSERT_TRUE (response->waitForEndStream ());
990
+ verifyResponse (std::move (response), " 200" , {}, {});
991
+
992
+ cleanupUpstreamAndDownstream ();
993
+ }
994
+
922
995
class OdCdsScopedRdsIntegrationTestBase : public ScopedRdsIntegrationTest {
923
996
public:
924
997
void addOnDemandConfig (OdCdsIntegrationHelper::OnDemandConfig config) {
0 commit comments