import (
"encoding/json"
"fmt"
+ "slices"
"sort"
"google.golang.org/grpc/internal/balancer/weight"
if endpoint.HealthStatus != xdsresource.EndpointHealthStatusHealthy && endpoint.HealthStatus != xdsresource.EndpointHealthStatusUnknown {
continue
}
- resolverEndpoint := resolver.Endpoint{}
- for _, as := range endpoint.Addresses {
- resolverEndpoint.Addresses = append(resolverEndpoint.Addresses, resolver.Address{Addr: as})
- }
+
+ // Create a copy of endpoint.ResolverEndpoint to avoid race between
+ // the xDS Client (which owns this shared object in its cache) and
+ // the Cluster Resolver (which is trying to modify attributes).
+ resolverEndpoint := endpoint.ResolverEndpoint
+ resolverEndpoint.Addresses = slices.Clone(endpoint.ResolverEndpoint.Addresses)
+
resolverEndpoint = hierarchy.SetInEndpoint(resolverEndpoint, []string{priorityName, localityStr})
resolverEndpoint = xdsinternal.SetLocalityIDInEndpoint(resolverEndpoint, locality.ID)
// "To provide the xds_wrr_locality load balancer information about
endpoints = append(endpoints, resolver.Endpoint{Addresses: []resolver.Address{{Addr: addr}}})
ends = append(ends, xdsresource.Endpoint{
HealthStatus: xdsresource.EndpointHealthStatusHealthy,
- Addresses: []string{
- addr,
- fmt.Sprintf("addr-%d-%d-additional-1", i, j),
- fmt.Sprintf("addr-%d-%d-additional-2", i, j),
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{
+ {Addr: addr},
+ {Addr: fmt.Sprintf("addr-%d-%d-additional-1", i, j)},
+ {Addr: fmt.Sprintf("addr-%d-%d-additional-2", i, j)},
+ },
},
})
}
Name: "pick_first",
},
}
- e1 := resolver.Endpoint{Addresses: []resolver.Address{{Addr: testEndpoints[0][0].Addresses[0]}}}
- e2 := resolver.Endpoint{Addresses: []resolver.Address{{Addr: testEndpoints[0][1].Addresses[0]}}}
+ e1 := resolver.Endpoint{Addresses: []resolver.Address{{Addr: testEndpoints[0][0].ResolverEndpoint.Addresses[0].Addr}}}
+ e2 := resolver.Endpoint{Addresses: []resolver.Address{{Addr: testEndpoints[0][1].ResolverEndpoint.Addresses[0].Addr}}}
wantEndpoints := []resolver.Endpoint{
hierarchy.SetInEndpoint(e1, []string{"priority-3"}),
hierarchy.SetInEndpoint(e2, []string{"priority-3"}),
},
}
wantEndpoints := []resolver.Endpoint{
- testEndpointWithAttrs(testEndpoints[0][0].Addresses, 20, 1, "priority-2-0", &testLocalityIDs[0]),
- testEndpointWithAttrs(testEndpoints[0][1].Addresses, 20, 1, "priority-2-0", &testLocalityIDs[0]),
- testEndpointWithAttrs(testEndpoints[1][0].Addresses, 80, 1, "priority-2-0", &testLocalityIDs[1]),
- testEndpointWithAttrs(testEndpoints[1][1].Addresses, 80, 1, "priority-2-0", &testLocalityIDs[1]),
- testEndpointWithAttrs(testEndpoints[2][0].Addresses, 20, 1, "priority-2-1", &testLocalityIDs[2]),
- testEndpointWithAttrs(testEndpoints[2][1].Addresses, 20, 1, "priority-2-1", &testLocalityIDs[2]),
- testEndpointWithAttrs(testEndpoints[3][0].Addresses, 80, 1, "priority-2-1", &testLocalityIDs[3]),
- testEndpointWithAttrs(testEndpoints[3][1].Addresses, 80, 1, "priority-2-1", &testLocalityIDs[3]),
+ testEndpointWithAttrs(testEndpoints[0][0].ResolverEndpoint, 20, 1, "priority-2-0", &testLocalityIDs[0]),
+ testEndpointWithAttrs(testEndpoints[0][1].ResolverEndpoint, 20, 1, "priority-2-0", &testLocalityIDs[0]),
+ testEndpointWithAttrs(testEndpoints[1][0].ResolverEndpoint, 80, 1, "priority-2-0", &testLocalityIDs[1]),
+ testEndpointWithAttrs(testEndpoints[1][1].ResolverEndpoint, 80, 1, "priority-2-0", &testLocalityIDs[1]),
+ testEndpointWithAttrs(testEndpoints[2][0].ResolverEndpoint, 20, 1, "priority-2-1", &testLocalityIDs[2]),
+ testEndpointWithAttrs(testEndpoints[2][1].ResolverEndpoint, 20, 1, "priority-2-1", &testLocalityIDs[2]),
+ testEndpointWithAttrs(testEndpoints[3][0].ResolverEndpoint, 80, 1, "priority-2-1", &testLocalityIDs[3]),
+ testEndpointWithAttrs(testEndpoints[3][1].ResolverEndpoint, 80, 1, "priority-2-1", &testLocalityIDs[3]),
}
if diff := cmp.Diff(gotNames, wantNames); diff != "" {
localities: []xdsresource.Locality{
{
Endpoints: []xdsresource.Endpoint{
- {Addresses: []string{"addr-1-1"}, HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 90},
- {Addresses: []string{"addr-1-2"}, HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 10},
+ {
+ ResolverEndpoint: resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-1-1"}}},
+ Weight: 90,
+ HealthStatus: xdsresource.EndpointHealthStatusHealthy,
+ },
+ {
+ ResolverEndpoint: resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-1-2"}}},
+ Weight: 10,
+ HealthStatus: xdsresource.EndpointHealthStatusHealthy,
+ },
},
ID: clients.Locality{Zone: "test-zone-1"},
Weight: 20,
},
{
Endpoints: []xdsresource.Endpoint{
- {Addresses: []string{"addr-2-1"}, HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 90},
- {Addresses: []string{"addr-2-2"}, HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 10},
+ {
+ ResolverEndpoint: resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-2-1"}}},
+ Weight: 90,
+ HealthStatus: xdsresource.EndpointHealthStatusHealthy,
+ },
+ {
+ ResolverEndpoint: resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-2-2"}}},
+ Weight: 10,
+ HealthStatus: xdsresource.EndpointHealthStatusHealthy,
+ },
},
ID: clients.Locality{Zone: "test-zone-2"},
Weight: 80,
ChildPolicy: &iserviceconfig.BalancerConfig{Name: roundrobin.Name},
},
wantEndpoints: []resolver.Endpoint{
- testEndpointWithAttrs([]string{"addr-1-1"}, 20, 90, "test-priority", &clients.Locality{Zone: "test-zone-1"}),
- testEndpointWithAttrs([]string{"addr-1-2"}, 20, 10, "test-priority", &clients.Locality{Zone: "test-zone-1"}),
- testEndpointWithAttrs([]string{"addr-2-1"}, 80, 90, "test-priority", &clients.Locality{Zone: "test-zone-2"}),
- testEndpointWithAttrs([]string{"addr-2-2"}, 80, 10, "test-priority", &clients.Locality{Zone: "test-zone-2"}),
+ testEndpointWithAttrs(resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-1-1"}}}, 20, 90, "test-priority", &clients.Locality{Zone: "test-zone-1"}),
+ testEndpointWithAttrs(resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-1-2"}}}, 20, 10, "test-priority", &clients.Locality{Zone: "test-zone-1"}),
+ testEndpointWithAttrs(resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-2-1"}}}, 80, 90, "test-priority", &clients.Locality{Zone: "test-zone-2"}),
+ testEndpointWithAttrs(resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-2-2"}}}, 80, 10, "test-priority", &clients.Locality{Zone: "test-zone-2"}),
},
},
{
localities: []xdsresource.Locality{
{
Endpoints: []xdsresource.Endpoint{
- {Addresses: []string{"addr-1-1"}, HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 90},
- {Addresses: []string{"addr-1-2"}, HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 10},
+ {
+ ResolverEndpoint: resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-1-1"}}},
+ Weight: 90,
+ HealthStatus: xdsresource.EndpointHealthStatusHealthy,
+ },
+ {
+ ResolverEndpoint: resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-1-2"}}},
+ Weight: 10,
+ HealthStatus: xdsresource.EndpointHealthStatusHealthy,
+ },
},
ID: clients.Locality{Zone: "test-zone-1"},
Weight: 20,
},
{
Endpoints: []xdsresource.Endpoint{
- {Addresses: []string{"addr-2-1"}, HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 90},
- {Addresses: []string{"addr-2-2"}, HealthStatus: xdsresource.EndpointHealthStatusHealthy, Weight: 10},
+ {
+ ResolverEndpoint: resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-2-1"}}},
+ Weight: 90,
+ HealthStatus: xdsresource.EndpointHealthStatusHealthy,
+ },
+ {
+ ResolverEndpoint: resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-2-2"}}},
+ Weight: 10,
+ HealthStatus: xdsresource.EndpointHealthStatusHealthy,
+ },
},
ID: clients.Locality{Zone: "test-zone-2"},
Weight: 80,
},
},
wantEndpoints: []resolver.Endpoint{
- testEndpointWithAttrs([]string{"addr-1-1"}, 20, 90, "test-priority", &clients.Locality{Zone: "test-zone-1"}),
- testEndpointWithAttrs([]string{"addr-1-2"}, 20, 10, "test-priority", &clients.Locality{Zone: "test-zone-1"}),
- testEndpointWithAttrs([]string{"addr-2-1"}, 80, 90, "test-priority", &clients.Locality{Zone: "test-zone-2"}),
- testEndpointWithAttrs([]string{"addr-2-2"}, 80, 10, "test-priority", &clients.Locality{Zone: "test-zone-2"}),
+ testEndpointWithAttrs(resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-1-1"}}}, 20, 90, "test-priority", &clients.Locality{Zone: "test-zone-1"}),
+ testEndpointWithAttrs(resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-1-2"}}}, 20, 10, "test-priority", &clients.Locality{Zone: "test-zone-1"}),
+ testEndpointWithAttrs(resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-2-1"}}}, 80, 90, "test-priority", &clients.Locality{Zone: "test-zone-2"}),
+ testEndpointWithAttrs(resolver.Endpoint{Addresses: []resolver.Address{{Addr: "addr-2-2"}}}, 80, 10, "test-priority", &clients.Locality{Zone: "test-zone-2"}),
},
},
}
}
}
-func testEndpointWithAttrs(addrStrs []string, localityWeight, endpointWeight uint32, priority string, lID *clients.Locality) resolver.Endpoint {
- endpoint := resolver.Endpoint{}
- for _, a := range addrStrs {
- endpoint.Addresses = append(endpoint.Addresses, resolver.Address{Addr: a})
- }
+func testEndpointWithAttrs(endpoint resolver.Endpoint, localityWeight, endpointWeight uint32, priority string, lID *clients.Locality) resolver.Endpoint {
path := []string{priority}
if lID != nil {
path = append(path, xdsinternal.LocalityString(*lID))
"google.golang.org/grpc/internal/xds/clients"
"google.golang.org/grpc/internal/xds/xdsclient"
"google.golang.org/grpc/internal/xds/xdsclient/xdsresource"
+ "google.golang.org/grpc/resolver"
"google.golang.org/protobuf/types/known/wrapperspb"
v3endpointpb "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost1, edsPort1)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost1, edsPort1)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost1, edsPort1)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost1, edsPort1)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost1, edsPort1)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost1, edsPort1)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost2, edsPort2)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost2, edsPort2)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost1, edsPort1)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost1, edsPort1)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost2, edsPort2)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost2, edsPort2)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost1, edsPort1)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost1, edsPort1)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost1, edsPort1)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost1, edsPort1)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost1, edsPort1)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost1, edsPort1)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{fmt.Sprintf("%s:%d", edsHost1, edsPort1)}, Weight: 1}},
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: fmt.Sprintf("%s:%d", edsHost1, edsPort1)}},
+ },
+ Weight: 1,
+ }},
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
"google.golang.org/grpc/internal/xds/clients"
"google.golang.org/grpc/internal/xds/xdsclient"
"google.golang.org/grpc/internal/xds/xdsclient/xdsresource"
+ "google.golang.org/grpc/resolver"
v3clusterpb "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
v3endpointpb "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
update: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{"localhost:666"}, Weight: 1}},
- Weight: 1,
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: "localhost:666"}},
+ },
+ Weight: 1,
+ }},
+ Weight: 1,
ID: clients.Locality{
Region: "region-1",
Zone: "zone-1",
"google.golang.org/grpc/internal/xds/clients"
"google.golang.org/grpc/internal/xds/xdsclient"
"google.golang.org/grpc/internal/xds/xdsclient/xdsresource"
+ "google.golang.org/grpc/resolver"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/anypb"
wantUpdate: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{"addr1:314"}, Weight: 1}},
- ID: clients.Locality{SubZone: "locality-1"},
- Priority: 1,
- Weight: 1,
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: "addr1:314"}},
+ },
+ Weight: 1,
+ }},
+ ID: clients.Locality{SubZone: "locality-1"},
+ Priority: 1,
+ Weight: 1,
},
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{"addr2:159"}, Weight: 1}},
- ID: clients.Locality{SubZone: "locality-2"},
- Priority: 0,
- Weight: 1,
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: "addr2:159"}},
+ },
+ Weight: 1,
+ }},
+ ID: clients.Locality{SubZone: "locality-2"},
+ Priority: 0,
+ Weight: 1,
},
},
},
wantUpdate: xdsresource.EndpointsUpdate{
Localities: []xdsresource.Locality{
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{"addr1:314"}, Weight: 1}},
- ID: clients.Locality{SubZone: "locality-1"},
- Priority: 1,
- Weight: 1,
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: "addr1:314"}},
+ },
+ Weight: 1,
+ }},
+ ID: clients.Locality{SubZone: "locality-1"},
+ Priority: 1,
+ Weight: 1,
},
{
- Endpoints: []xdsresource.Endpoint{{Addresses: []string{"addr2:159"}, Weight: 1}},
- ID: clients.Locality{SubZone: "locality-2"},
- Priority: 0,
- Weight: 1,
+ Endpoints: []xdsresource.Endpoint{{
+ ResolverEndpoint: resolver.Endpoint{
+ Addresses: []resolver.Address{{Addr: "addr2:159"}},
+ },
+ Weight: 1,
+ }},
+ ID: clients.Locality{SubZone: "locality-2"},
+ Priority: 0,
+ Weight: 1,
},
},
},
import (
"google.golang.org/grpc/internal/xds/clients"
+ "google.golang.org/grpc/resolver"
"google.golang.org/protobuf/types/known/anypb"
)
)
// Endpoint contains information of an endpoint.
+// TODO(i/8757) : Replace Endpoint with resolver.Endpoint struct.
type Endpoint struct {
- Addresses []string
- HealthStatus EndpointHealthStatus
- Weight uint32
- HashKey string
- Metadata map[string]any
- Hostname string
+ ResolverEndpoint resolver.Endpoint
+ HealthStatus EndpointHealthStatus
+ Weight uint32
+ HashKey string
+ Metadata map[string]any
}
// Locality contains information of a locality.
"google.golang.org/grpc/internal/pretty"
xdsinternal "google.golang.org/grpc/internal/xds"
"google.golang.org/grpc/internal/xds/clients"
+ "google.golang.org/grpc/resolver"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
)
+// hostnameKeyType is the key to store the hostname attribute in
+// a resolver.Endpoint.
+type hostnameKeyType struct{}
+
+// setHostname returns a copy of the given endpoint with hostname added
+// as an attribute.
+func setHostname(endpoint resolver.Endpoint, hostname string) resolver.Endpoint {
+ // Only set if non-empty; xds_cluster_impl uses this to trigger :authority
+ // rewriting.
+ if hostname == "" {
+ return endpoint
+ }
+ endpoint.Attributes = endpoint.Attributes.WithValue(hostnameKeyType{}, hostname)
+ return endpoint
+}
+
+// HostnameFromEndpoint returns the hostname attribute of endpoint. If this
+// attribute is not set, it returns the empty string.
+func HostnameFromEndpoint(endpoint resolver.Endpoint) string {
+ hostname, _ := endpoint.Attributes.Value(hostnameKeyType{}).(string)
+ return hostname
+}
+
func unmarshalEndpointsResource(r *anypb.Any) (string, EndpointsUpdate, error) {
r, err := UnwrapResource(r)
if err != nil {
}
}
+ address := []resolver.Address{}
for _, a := range addrs {
+ address = append(address, resolver.Address{Addr: a})
if uniqueEndpointAddrs[a] {
return nil, fmt.Errorf("duplicate endpoint with the same address %s", a)
}
hashKey = hashKeyFromMetadata(endpointMetadata)
}
}
+ endpoint := resolver.Endpoint{Addresses: address}
+ endpoint = setHostname(endpoint, lbEndpoint.GetEndpoint().GetHostname())
endpoints = append(endpoints, Endpoint{
- HealthStatus: EndpointHealthStatus(lbEndpoint.GetHealthStatus()),
- Addresses: addrs,
- Weight: weight,
- HashKey: hashKey,
- Metadata: endpointMetadata,
- Hostname: lbEndpoint.GetEndpoint().GetHostname(),
+ ResolverEndpoint: endpoint,
+ HealthStatus: EndpointHealthStatus(lbEndpoint.GetHealthStatus()),
+ Weight: weight,
+ HashKey: hashKey,
+ Metadata: endpointMetadata,
})
}
return endpoints, nil
"google.golang.org/grpc/internal/testutils"
"google.golang.org/grpc/internal/xds/clients"
"google.golang.org/grpc/internal/xds/xdsclient/xdsresource/version"
+ "google.golang.org/grpc/resolver"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
+func buildResolverEndpoint(addr []string, hostname string) resolver.Endpoint {
+ address := []resolver.Address{}
+ for _, a := range addr {
+ address = append(address, resolver.Address{Addr: a})
+ }
+ resolverEndpoint := resolver.Endpoint{Addresses: address}
+ resolverEndpoint = setHostname(resolverEndpoint, hostname)
+ return resolverEndpoint
+}
+
func (s) TestEDSParseRespProto(t *testing.T) {
tests := []struct {
name string
m: func() *v3endpointpb.ClusterLoadAssignment {
clab0 := newClaBuilder("test", nil)
endpoints1 := []endpointOpts{{addrWithPort: "addr1:314"}}
- locOption1 := &addLocalityOptions{
- Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_HEALTHY},
- }
+ locOption1 := &addLocalityOptions{Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_HEALTHY}}
clab0.addLocality("locality-1", 0, 1, endpoints1, locOption1)
endpoints2 := []endpointOpts{{addrWithPort: "addr2:159"}}
- locOption2 := &addLocalityOptions{
- Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_HEALTHY},
- }
+ locOption2 := &addLocalityOptions{Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_HEALTHY}}
clab0.addLocality("locality-2", 0, 0, endpoints2, locOption2)
return clab0.Build()
}(),
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnhealthy,
- Weight: 271,
- Hostname: "addr1",
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnhealthy,
+ Weight: 271,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 1,
},
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr2:159"},
- HealthStatus: EndpointHealthStatusDraining,
- Weight: 828,
- Hostname: "addr2",
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr2:159"}, "addr2"),
+ HealthStatus: EndpointHealthStatusDraining,
+ Weight: 828,
}},
ID: clients.Locality{SubZone: "locality-2"},
Priority: 0,
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnhealthy,
- Weight: 271,
- Hostname: "addr1",
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnhealthy,
+ Weight: 271,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 1,
},
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr2:159"},
- HealthStatus: EndpointHealthStatusDraining,
- Weight: 828,
- Hostname: "addr2",
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr2:159"}, "addr2"),
+ HealthStatus: EndpointHealthStatusDraining,
+ Weight: 828,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
name: "multiple localities",
m: func() *v3endpointpb.ClusterLoadAssignment {
clab0 := newClaBuilder("test", nil)
- endpoints1 := []endpointOpts{{addrWithPort: "addr1:997", additionalAddrWithPorts: []string{"addr1:1000"}}}
+ endpoints1 := []endpointOpts{{addrWithPort: "addr1:997", additionalAddrWithPorts: []string{"addr1:1000"}, hostname: "addr1"}}
locOption1 := &addLocalityOptions{
Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_UNHEALTHY},
Weight: []uint32{271},
}
clab0.addLocality("locality-1", 1, 1, endpoints1, locOption1)
- endpoints2 := []endpointOpts{{addrWithPort: "addr2:998", additionalAddrWithPorts: []string{"addr2:1000"}}}
+ endpoints2 := []endpointOpts{{addrWithPort: "addr2:998", additionalAddrWithPorts: []string{"addr2:1000"}, hostname: "addr2"}}
locOption2 := &addLocalityOptions{
Health: []v3corepb.HealthStatus{v3corepb.HealthStatus_HEALTHY},
Weight: []uint32{828},
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:997", "addr1:1000"},
- HealthStatus: EndpointHealthStatusUnhealthy,
- Weight: 271,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:997", "addr1:1000"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnhealthy,
+ Weight: 271,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 1,
},
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr2:998", "addr2:1000"},
- HealthStatus: EndpointHealthStatusHealthy,
- Weight: 828,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr2:998", "addr2:1000"}, "addr2"),
+ HealthStatus: EndpointHealthStatusHealthy,
+ Weight: 828,
}},
ID: clients.Locality{SubZone: "locality-2"},
Priority: 0,
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnhealthy,
- Weight: 271,
- Hostname: "addr1",
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnhealthy,
+ Weight: 271,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 1,
},
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr2:159"},
- HealthStatus: EndpointHealthStatusDraining,
- Weight: 828,
- Hostname: "addr2",
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr2:159"}, "addr2"),
+ HealthStatus: EndpointHealthStatusDraining,
+ Weight: 828,
}},
ID: clients.Locality{SubZone: "locality-2"},
Priority: 0,
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnhealthy,
- Weight: 271,
- Hostname: "addr1",
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnhealthy,
+ Weight: 271,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 1,
},
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr2:159"},
- HealthStatus: EndpointHealthStatusDraining,
- Weight: 828,
- Hostname: "addr2",
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr2:159"}, "addr2"),
+ HealthStatus: EndpointHealthStatusDraining,
+ Weight: 828,
}},
ID: clients.Locality{SubZone: "locality-2"},
Priority: 0,
}),
},
},
+ hostname: "addr1",
}}
clab0.addLocality("locality-1", 1, 0, endpoints, nil)
return clab0.Build()
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
Metadata: map[string]any{
"test-key": ProxyAddressMetadataValue{
Address: "1.2.3.4:1111",
},
},
},
+ hostname: "addr1",
}}
clab0.addLocality("locality-1", 1, 0, endpoints, nil)
return clab0.Build()
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
Metadata: map[string]any{
"test-key": StructMetadataValue{Data: map[string]any{
"key": float64(123),
name: "typed_filter_metadata_in_locality",
endpointProto: func() *v3endpointpb.ClusterLoadAssignment {
clab0 := newClaBuilder("test", nil)
- endpoints := []endpointOpts{{addrWithPort: "addr1:314"}}
+ endpoints := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}
locOption := &addLocalityOptions{
Metadata: &v3corepb.Metadata{
TypedFilterMetadata: map[string]*anypb.Any{
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
name: "filter_metadata_in_locality",
endpointProto: func() *v3endpointpb.ClusterLoadAssignment {
clab0 := newClaBuilder("test", nil)
- endpoints := []endpointOpts{{addrWithPort: "addr1:314"}}
+ endpoints := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}
locOption := &addLocalityOptions{
Metadata: &v3corepb.Metadata{
FilterMetadata: map[string]*structpb.Struct{
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
},
},
},
+ hostname: "addr1",
}}
clab0.addLocality("locality-1", 1, 0, endpoints, nil)
return clab0.Build()
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
Metadata: map[string]any{
"test-key": ProxyAddressMetadataValue{
Address: "1.2.3.4:1111",
name: "typed_filter_metadata_over_filter_metadata_in_locality",
endpointProto: func() *v3endpointpb.ClusterLoadAssignment {
clab0 := newClaBuilder("test", nil)
- endpoints := []endpointOpts{{addrWithPort: "addr1:314"}}
+ endpoints := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}
locOption := &addLocalityOptions{
Metadata: &v3corepb.Metadata{
TypedFilterMetadata: map[string]*anypb.Any{
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
},
},
},
+ hostname: "addr1",
}}
clab0.addLocality("locality-1", 1, 0, endpoints, nil)
return clab0.Build()
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
Metadata: map[string]any{
"test-key": ProxyAddressMetadataValue{
Address: "1.2.3.4:1111",
name: "both_filter_and_typed_filter_metadata_in_locality",
endpointProto: func() *v3endpointpb.ClusterLoadAssignment {
clab0 := newClaBuilder("test", nil)
- endpoints := []endpointOpts{{addrWithPort: "addr1:314"}}
+ endpoints := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}
locOption := &addLocalityOptions{
Metadata: &v3corepb.Metadata{
TypedFilterMetadata: map[string]*anypb.Any{
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
}),
},
},
+ hostname: "addr1",
}}
clab0.addLocality("locality-1", 1, 0, endpoints, nil)
return clab0.Build()
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
},
},
},
+ hostname: "addr1",
}}
clab0.addLocality("locality-1", 1, 0, endpoints, nil)
return clab0.Build()
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
name: "typed_filter_metadata_in_locality",
endpointProto: func() *v3endpointpb.ClusterLoadAssignment {
clab0 := newClaBuilder("test", nil)
- endpoints := []endpointOpts{{addrWithPort: "addr1:314"}}
+ endpoints := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}
locOption := &addLocalityOptions{
Metadata: &v3corepb.Metadata{
TypedFilterMetadata: map[string]*anypb.Any{
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
name: "filter_metadata_in_locality",
endpointProto: func() *v3endpointpb.ClusterLoadAssignment {
clab0 := newClaBuilder("test", nil)
- endpoints := []endpointOpts{{addrWithPort: "addr1:314"}}
+ endpoints := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}
locOption := &addLocalityOptions{
Metadata: &v3corepb.Metadata{
FilterMetadata: map[string]*structpb.Struct{
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
},
},
},
+ hostname: "addr1",
}}
clab0.addLocality("locality-1", 1, 0, endpoints, nil)
return clab0.Build()
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
name: "both_filter_and_typed_filter_metadata_in_locality",
endpointProto: func() *v3endpointpb.ClusterLoadAssignment {
clab0 := newClaBuilder("test", nil)
- endpoints := []endpointOpts{{addrWithPort: "addr1:314"}}
+ endpoints := []endpointOpts{{addrWithPort: "addr1:314", hostname: "addr1"}}
locOption := &addLocalityOptions{
Metadata: &v3corepb.Metadata{
TypedFilterMetadata: map[string]*anypb.Any{
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
}),
},
},
+ hostname: "addr1",
}}
locOption := &addLocalityOptions{
Metadata: &v3corepb.Metadata{
Localities: []Locality{
{
Endpoints: []Endpoint{{
- Addresses: []string{"addr1:314"},
- HealthStatus: EndpointHealthStatusUnknown,
- Weight: 1,
+ ResolverEndpoint: buildResolverEndpoint([]string{"addr1:314"}, "addr1"),
+ HealthStatus: EndpointHealthStatusUnknown,
+ Weight: 1,
}},
ID: clients.Locality{SubZone: "locality-1"},
Priority: 0,
// An Endpoint is one network endpoint, or server, which may have multiple
// addresses with which it can be accessed.
+// TODO(i/8773) : make resolver.Endpoint and resolver.Address immutable
type Endpoint struct {
// Addresses contains a list of addresses used to access this endpoint.
Addresses []Address