func processLdsResponse()

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")
}