in dp_check/dp_check.go [707:769]
func processLdsResponse(ldsReply *v3discoverypb.DiscoveryResponse) (string, error) {
if len(ldsReply.GetResources()) == 0 {
return "", fmt.Errorf("no listener resource received in LDS response")
}
if len(ldsReply.GetResources()) != 1 {
return "", fmt.Errorf("expect to receive only 1 listener resource in LDS response, but received %v. This is not necessarily a violation of the XDS protocol, but it is not supported by (this version) of the dp_check tool", len(ldsReply.GetResources()))
}
resource := ldsReply.GetResources()[0]
lis := &v3listenerpb.Listener{}
if err := proto.Unmarshal(resource.GetValue(), lis); err != nil {
return "", fmt.Errorf("failed to unmarshal listener resource from LDS response: %v", err)
}
if lis.GetName() != *service {
return "", fmt.Errorf("listener resource name |%v| does not match |%v|", lis.GetName(), *service)
}
apiLis := &v3httppb.HttpConnectionManager{}
if err := proto.Unmarshal(lis.GetApiListener().GetApiListener().GetValue(), apiLis); err != nil {
return "", fmt.Errorf("failed to unmarshal api_listener resource from LDS response: %v", err)
}
switch apiLis.RouteSpecifier.(type) {
// TODO(mohanli): Add RDS support when processing LDS response
case *v3httppb.HttpConnectionManager_Rds:
return "", fmt.Errorf("route resource type in LDS response is RDS, which is currently not supported in dp_check")
case *v3httppb.HttpConnectionManager_RouteConfig:
infoLog.Printf("route resource type in LDS response is route_config")
for _, vh := range apiLis.GetRouteConfig().GetVirtualHosts() {
infoLog.Printf("virtual host: |%+v|", vh)
// The domains field of the VirtualHost must match the backend service
if len(vh.GetDomains()) == 0 {
infoLog.Printf("no domain received in this virtual_host, skip this virtual_host")
continue
}
if vh.GetDomains()[0] != "*" && vh.GetDomains()[0] != *service {
infoLog.Printf("received a virtual_host whose domain is |%v|, which does not match |%v|, skip this virtual_host", vh.GetDomains()[0], *service)
continue
}
// In the initial gRPC xDS design, only interested the default route (the last one)
if len(vh.GetRoutes()) == 0 {
infoLog.Printf("no routes received in virtual_host, skip")
continue
}
route := vh.GetRoutes()[len(vh.GetRoutes())-1]
// The match field in the route must contains a prefix field,
// and the prefix field must be an empty string
match := route.GetMatch()
if match == nil {
infoLog.Printf("match field must exist, but it is nil, skip this virtual_host")
continue
}
if match.GetPrefix() != "" {
infoLog.Printf("match field in default route must have an empty prefix, but it is |%v|, skip this virtual_host", match.GetPrefix())
continue
}
// Get cluster name
return route.GetRoute().GetCluster(), nil
}
case nil:
return "", fmt.Errorf("no route resource in LDS response")
default:
return "", fmt.Errorf("unknown route resource type in LDS response: %v", apiLis.RouteSpecifier)
}
return "", fmt.Errorf("no matching cluster name found in LDS response")
}