Repository: envoyproxy/go-control-plane (Go)

Issue:
the resource order is not in line with the description in the xds doc
It looks like the current order is not in line with the description in the xds doc.

The order in the current implementation: Listener -> Route -> Cluster -> Endpoint
According to xds doc, the order should be like: Cluster -> Endpoint -> Listener -> Route 

References:

https://www.envoyproxy.io/docs/envoy/latest/api-docs/xds_protocol#eventual-consistency-considerations

```
In general, to avoid traffic drop, sequencing of updates should follow a make before break model, wherein:

CDS updates (if any) must always be pushed first.

EDS updates (if any) must arrive after CDS updates for the respective clusters.

LDS updates must arrive after corresponding CDS/EDS updates.

RDS updates related to the newly added listeners must arrive after CDS/EDS/LDS updates.

VHDS updates (if any) related to the newly added RouteConfigurations must arrive after RDS updates.

Stale CDS clusters and related EDS endpoints (ones no longer being referenced) can then be removed.
```

https://github.com/envoyproxy/go-control-plane/blob/52093cd01fd1a94d243081f6dec566db6987c145/pkg/cache/v3/order_test.go#L66-L71




Discussion:
@zhaohuabing Thanks for creating the bug




Patch:
diff --git a/pkg/cache/types/types.go b/pkg/cache/types/types.go
index de1dac8363..ffaf0a9774 100644
--- a/pkg/cache/types/types.go
+++ b/pkg/cache/types/types.go
@@ -43,12 +43,12 @@ type ResponseType int
 // ADS expects things to be returned in a specific order.
 // See the following issue for details: https://github.com/envoyproxy/go-control-plane/issues/526
 const (
-	Endpoint ResponseType = iota
-	Cluster
-	ScopedRoute
+	Cluster ResponseType = iota
+	Endpoint
+	Listener
 	Route
+	ScopedRoute
 	VirtualHost
-	Listener
 	Secret
 	Runtime
 	ExtensionConfig
diff --git a/pkg/cache/v3/order.go b/pkg/cache/v3/order.go
index b27795022e..c416946e82 100644
--- a/pkg/cache/v3/order.go
+++ b/pkg/cache/v3/order.go
@@ -16,7 +16,7 @@ func (k keys) Len() int {
 
 // Less compares the typeURL and determines what order things should be sent.
 func (k keys) Less(i, j int) bool {
-	return GetResponseType(k[i].TypeURL) > GetResponseType(k[j].TypeURL)
+	return GetResponseType(k[i].TypeURL) < GetResponseType(k[j].TypeURL)
 }
 
 func (k keys) Swap(i, j int) {


Test patch:
diff --git a/pkg/cache/v3/order_test.go b/pkg/cache/v3/order_test.go
index bed86fd260..c7f1ac2891 100644
--- a/pkg/cache/v3/order_test.go
+++ b/pkg/cache/v3/order_test.go
@@ -33,6 +33,14 @@ func TestOrderKeys(t *testing.T) {
 		},
 	}
 	expected := keys{
+		{
+			ID:      2,
+			TypeURL: resource.ClusterType,
+		},
+		{
+			ID:      1,
+			TypeURL: resource.EndpointType,
+		},
 		{
 			ID:      4,
 			TypeURL: resource.ListenerType,
@@ -45,14 +53,6 @@ func TestOrderKeys(t *testing.T) {
 			ID:      5,
 			TypeURL: resource.ScopedRouteType,
 		},
-		{
-			ID:      2,
-			TypeURL: resource.ClusterType,
-		},
-		{
-			ID:      1,
-			TypeURL: resource.EndpointType,
-		},
 	}
 
 	orderedKeys := unorderedKeys
@@ -64,9 +64,9 @@ func TestOrderKeys(t *testing.T) {
 
 	// Ordering:
 	// === RUN   TestOrderKeys
+	// order_test.go:43: {ID:2 TypeURL:type.googleapis.com/envoy.config.cluster.v3.Cluster}
+	// order_test.go:43: {ID:1 TypeURL:type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment}
 	// order_test.go:43: {ID:4 TypeURL:type.googleapis.com/envoy.config.listener.v3.Listener}
 	// order_test.go:43: {ID:3 TypeURL:type.googleapis.com/envoy.config.route.v3.RouteConfiguration}
 	// order_test.go:43: {ID:5 TypeURL:type.googleapis.com/envoy.config.route.v3.ScopedRouteConfiguration}
-	// order_test.go:43: {ID:2 TypeURL:type.googleapis.com/envoy.config.cluster.v3.Cluster}
-	// order_test.go:43: {ID:1 TypeURL:type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment}
 }