Repository: grpc/grpc-go
File: internal/xds/balancer/clusterresolver/configbuilder.go (Go)

Code before:
}

func convertClusterImplMapToOutlierDetection(ciCfgs map[string]*clusterimpl.LBConfig, odCfg outlierdetection.LBConfig) map[string]*outlierdetection.LBConfig {
	odCfgs := make(map[string]*outlierdetection.LBConfig, len(ciCfgs))
	for n, c := range ciCfgs {
		odCfgs[n] = makeClusterImplOutlierDetectionChild(c, odCfg)
	}
	return odCfgs
}

func makeClusterImplOutlierDetectionChild(ciCfg *clusterimpl.LBConfig, odCfg outlierdetection.LBConfig) *outlierdetection.LBConfig {
	odCfgRet := odCfg
	odCfgRet.ChildPolicy = &internalserviceconfig.BalancerConfig{Name: clusterimpl.Name, Config: ciCfg}
	return &odCfgRet
}

func buildClusterImplConfigForDNS(g *nameGenerator, endpoints []resolver.Endpoint, mechanism DiscoveryMechanism, xdsLBPolicy *internalserviceconfig.BalancerConfig) (string, *clusterimpl.LBConfig, []resolver.Endpoint) {
	pName := fmt.Sprintf("priority-%v", g.prefix)
	if len(endpoints) == 0 {
		return pName, &clusterimpl.LBConfig{
			Cluster:               mechanism.Cluster,
			TelemetryLabels:       mechanism.TelemetryLabels,
			ChildPolicy:           xdsLBPolicy,
			MaxConcurrentRequests: mechanism.MaxConcurrentRequests,
			LoadReportingServer:   mechanism.LoadReportingServer,
		}, []resolver.Endpoint{}
	}
	var retEndpoint resolver.Endpoint
	for _, e := range endpoints {
		// Copy the nested address field as slice fields are shared by the
		// iteration variable and the original slice.
		retEndpoint.Addresses = append(retEndpoint.Addresses, e.Addresses...)
	}
	localityStr := xdsinternal.LocalityString(clients.Locality{})
	retEndpoint = hierarchy.SetInEndpoint(retEndpoint, []string{pName, localityStr})
	// Set the locality weight to 1. This is required because the child policy
	// like wrr which relies on locality weights to distribute traffic. These
	// policies may drop traffic if the weight is 0.
	retEndpoint = wrrlocality.SetAddrInfoInEndpoint(retEndpoint, wrrlocality.AddrInfo{LocalityWeight: 1})
	return pName, &clusterimpl.LBConfig{
		Cluster:               mechanism.Cluster,
		TelemetryLabels:       mechanism.TelemetryLabels,
		ChildPolicy:           xdsLBPolicy,
		MaxConcurrentRequests: mechanism.MaxConcurrentRequests,
		LoadReportingServer:   mechanism.LoadReportingServer,
	}, []resolver.Endpoint{retEndpoint}
}

// buildClusterImplConfigForEDS returns a list of cluster_impl configs, one for
// each priority, sorted by priority, and the addresses for each priority (with
// hierarchy attributes set).

Review comment (suggestion):
Can this return a `nil` slice instead? It is not a good idea to have an API that differentiates between empty and `nil` slices. See: go/go-style/decisions#nil-slices

Code after:
}

func convertClusterImplMapToOutlierDetection(ciCfgs map[string]*clusterimpl.LBConfig, odCfg outlierdetection.LBConfig) map[string]*outlierdetection.LBConfig {
	odCfgs := make(map[string]*outlierdetection.LBConfig, len(ciCfgs))
	for n, c := range ciCfgs {
		odCfgs[n] = makeClusterImplOutlierDetectionChild(c, odCfg)
	}
	return odCfgs
}

func makeClusterImplOutlierDetectionChild(ciCfg *clusterimpl.LBConfig, odCfg outlierdetection.LBConfig) *outlierdetection.LBConfig {
	odCfgRet := odCfg
	odCfgRet.ChildPolicy = &internalserviceconfig.BalancerConfig{Name: clusterimpl.Name, Config: ciCfg}
	return &odCfgRet
}

func buildClusterImplConfigForDNS(g *nameGenerator, endpoints []resolver.Endpoint, mechanism DiscoveryMechanism, xdsLBPolicy *internalserviceconfig.BalancerConfig) (string, *clusterimpl.LBConfig, []resolver.Endpoint) {
	pName := fmt.Sprintf("priority-%v", g.prefix)
	lbconfig := &clusterimpl.LBConfig{
		Cluster:               mechanism.Cluster,
		TelemetryLabels:       mechanism.TelemetryLabels,
		ChildPolicy:           xdsLBPolicy,
		MaxConcurrentRequests: mechanism.MaxConcurrentRequests,
		LoadReportingServer:   mechanism.LoadReportingServer,
	}
	if len(endpoints) == 0 {
		return pName, lbconfig, nil
	}
	var retEndpoint resolver.Endpoint
	for _, e := range endpoints {
		// LOGICAL_DNS requires all resolved addresses to be grouped into a
		// single logical endpoint. We iterate over the input endpoints and
		// aggregate their addresses into a new endpoint variable.
		retEndpoint.Addresses = append(retEndpoint.Addresses, e.Addresses...)
	}
	// Even though localities are not a thing for the LOGICAL_DNS cluster and
	// its endpoint(s), we add an empty locality attribute here to ensure that
	// LB policies that rely on locality information (like weighted_target)
	// continue to work.
	localityStr := xdsinternal.LocalityString(clients.Locality{})
	retEndpoint = xdsresource.SetHostname(hierarchy.SetInEndpoint(retEndpoint, []string{pName, localityStr}), mechanism.DNSHostname)
	// Set the locality weight to 1. This is required because the child policy
	// like weighted_target which relies on locality weights to distribute
	// traffic. These policies may drop traffic if the weight is 0.
	retEndpoint = wrrlocality.SetAddrInfo(retEndpoint, wrrlocality.AddrInfo{LocalityWeight: 1})
	return pName, lbconfig, []resolver.Endpoint{retEndpoint}
}

// buildClusterImplConfigForEDS returns a list of cluster_impl configs, one for
// each priority, sorted by priority, and the addresses for each priority (with
// hierarchy attributes set).