Skip to content

Commit 2f9bb38

Browse files
purnesh42HPranjali-2501
authored andcommitted
xdsclient: relay marshalled bytes of complete resource proto to decoders (#8422)
1 parent fa3ec85 commit 2f9bb38

File tree

5 files changed

+59
-30
lines changed

5 files changed

+59
-30
lines changed

xds/internal/clients/xdsclient/channel.go

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -253,20 +253,10 @@ func decodeResponse(opts *DecodeOptions, rType *ResourceType, resp response) (ma
253253
perResourceErrors := make(map[string]error) // Tracks resource validation errors, where we have a resource name.
254254
ret := make(map[string]dataAndErrTuple) // Return result, a map from resource name to either resource data or error.
255255
for _, r := range resp.resources {
256-
// Unwrap and validate the resource, but preserve the original bytes for
257-
// decoding. This is required for resource types that don't have a name
258-
// field in the resource itself, but only have one in the wrapped
259-
// resource.
260-
inner, err := xdsresource.UnwrapResource(r)
261-
if err != nil {
262-
topLevelErrors = append(topLevelErrors, err)
263-
continue
264-
}
265-
if _, ok := opts.Config.ResourceTypes[inner.GetTypeUrl()]; !ok || inner.GetTypeUrl() != resp.typeURL {
266-
topLevelErrors = append(topLevelErrors, xdsresource.NewErrorf(xdsresource.ErrorTypeResourceTypeUnsupported, "unexpected resource type: %q ", inner.GetTypeUrl()))
267-
continue
268-
}
269-
result, err := rType.Decoder.Decode(r.GetValue(), *opts)
256+
result, err := rType.Decoder.Decode(AnyProto{
257+
TypeURL: r.GetTypeUrl(),
258+
Value: r.GetValue(),
259+
}, *opts)
270260

271261
// Name field of the result is left unpopulated only when resource
272262
// deserialization fails.

xds/internal/clients/xdsclient/helpers_test.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"google.golang.org/grpc/xds/internal/clients/internal/pretty"
3131
"google.golang.org/grpc/xds/internal/clients/xdsclient/internal/xdsresource"
3232
"google.golang.org/protobuf/proto"
33+
"google.golang.org/protobuf/types/known/anypb"
3334

3435
v3listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
3536
v3httppb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
@@ -62,17 +63,24 @@ var (
6263
}
6364
)
6465

65-
func unmarshalListenerResource(r []byte) (string, listenerUpdate, error) {
66+
func unmarshalListenerResource(rProto *anypb.Any) (string, listenerUpdate, error) {
67+
rProto, err := xdsresource.UnwrapResource(rProto)
68+
if err != nil {
69+
return "", listenerUpdate{}, fmt.Errorf("failed to unwrap resource: %v", err)
70+
}
71+
if !xdsresource.IsListenerResource(rProto.GetTypeUrl()) {
72+
return "", listenerUpdate{}, fmt.Errorf("unexpected listener resource type: %q", rProto.GetTypeUrl())
73+
}
6674
lis := &v3listenerpb.Listener{}
67-
if err := proto.Unmarshal(r, lis); err != nil {
75+
if err := proto.Unmarshal(rProto.GetValue(), lis); err != nil {
6876
return "", listenerUpdate{}, fmt.Errorf("failed to unmarshal resource: %v", err)
6977
}
7078

7179
lu, err := processListener(lis)
7280
if err != nil {
7381
return lis.GetName(), listenerUpdate{}, err
7482
}
75-
lu.Raw = r
83+
lu.Raw = rProto.GetValue()
7684
return lis.GetName(), *lu, nil
7785
}
7886

@@ -154,8 +162,12 @@ type listenerDecoder struct{}
154162

155163
// Decode deserializes and validates an xDS resource serialized inside the
156164
// provided `Any` proto, as received from the xDS management server.
157-
func (listenerDecoder) Decode(resource []byte, _ DecodeOptions) (*DecodeResult, error) {
158-
name, listener, err := unmarshalListenerResource(resource)
165+
func (listenerDecoder) Decode(resource AnyProto, _ DecodeOptions) (*DecodeResult, error) {
166+
rProto := &anypb.Any{
167+
TypeUrl: resource.TypeURL,
168+
Value: resource.Value,
169+
}
170+
name, listener, err := unmarshalListenerResource(rProto)
159171
switch {
160172
case name == "":
161173
// Name is unset only when protobuf deserialization fails.

xds/internal/clients/xdsclient/resource_type.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,21 @@ type Decoder interface {
5151
// Decode deserializes and validates an xDS resource as received from the
5252
// xDS management server.
5353
//
54-
// If deserialization fails or resource validation fails, it returns a
55-
// non-nil error. Otherwise, returns a fully populated DecodeResult.
56-
Decode(resource []byte, options DecodeOptions) (*DecodeResult, error)
54+
// The `resource` parameter may contain a value of the serialized wrapped
55+
// resource (i.e. with the type URL
56+
// `type.googleapis.com/envoy.service.discovery.v3.Resource`).
57+
// Implementations are responsible for unwrapping the underlying resource if
58+
// it is wrapped.
59+
//
60+
// If unmarshalling or validation fails, it returns a non-nil error.
61+
// Otherwise, returns a fully populated DecodeResult.
62+
Decode(resource AnyProto, options DecodeOptions) (*DecodeResult, error)
63+
}
64+
65+
// AnyProto contains the type URL and serialized proto data of an xDS resource.
66+
type AnyProto struct {
67+
TypeURL string
68+
Value []byte
5769
}
5870

5971
// DecodeOptions wraps the options required by ResourceType implementations for

xds/internal/clients/xdsclient/test/helpers_test.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"google.golang.org/grpc/xds/internal/clients/xdsclient"
3535
"google.golang.org/grpc/xds/internal/clients/xdsclient/internal/xdsresource"
3636
"google.golang.org/protobuf/proto"
37+
"google.golang.org/protobuf/types/known/anypb"
3738

3839
v3listenerpb "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
3940
v3httppb "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/network/http_connection_manager/v3"
@@ -73,17 +74,24 @@ var (
7374
}
7475
)
7576

76-
func unmarshalListenerResource(r []byte) (string, listenerUpdate, error) {
77+
func unmarshalListenerResource(rProto *anypb.Any) (string, listenerUpdate, error) {
78+
rProto, err := xdsresource.UnwrapResource(rProto)
79+
if err != nil {
80+
return "", listenerUpdate{}, fmt.Errorf("failed to unwrap resource: %v", err)
81+
}
82+
if !xdsresource.IsListenerResource(rProto.GetTypeUrl()) {
83+
return "", listenerUpdate{}, fmt.Errorf("unexpected listener resource type: %q", rProto.GetTypeUrl())
84+
}
7785
lis := &v3listenerpb.Listener{}
78-
if err := proto.Unmarshal(r, lis); err != nil {
86+
if err := proto.Unmarshal(rProto.GetValue(), lis); err != nil {
7987
return "", listenerUpdate{}, fmt.Errorf("failed to unmarshal resource: %v", err)
8088
}
8189

8290
lu, err := processListener(lis)
8391
if err != nil {
8492
return lis.GetName(), listenerUpdate{}, err
8593
}
86-
lu.Raw = r
94+
lu.Raw = rProto.GetValue()
8795
return lis.GetName(), *lu, nil
8896
}
8997

@@ -165,8 +173,12 @@ type listenerDecoder struct{}
165173

166174
// Decode deserializes and validates an xDS resource serialized inside the
167175
// provided `Any` proto, as received from the xDS management server.
168-
func (listenerDecoder) Decode(resource []byte, _ xdsclient.DecodeOptions) (*xdsclient.DecodeResult, error) {
169-
name, listener, err := unmarshalListenerResource(resource)
176+
func (listenerDecoder) Decode(resource xdsclient.AnyProto, _ xdsclient.DecodeOptions) (*xdsclient.DecodeResult, error) {
177+
rProto := &anypb.Any{
178+
TypeUrl: resource.TypeURL,
179+
Value: resource.Value,
180+
}
181+
name, listener, err := unmarshalListenerResource(rProto)
170182
switch {
171183
case name == "":
172184
// Name is unset only when protobuf deserialization fails.

xds/internal/xdsclient/xdsresource/resource_type.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,14 +184,17 @@ type GenericResourceTypeDecoder struct {
184184

185185
// Decode deserialize and validate resource bytes of an xDS resource received
186186
// from the xDS management server.
187-
func (gd *GenericResourceTypeDecoder) Decode(resourceBytes []byte, gOpts xdsclient.DecodeOptions) (*xdsclient.DecodeResult, error) {
188-
raw := &anypb.Any{TypeUrl: gd.ResourceType.TypeURL(), Value: resourceBytes}
187+
func (gd *GenericResourceTypeDecoder) Decode(resource xdsclient.AnyProto, gOpts xdsclient.DecodeOptions) (*xdsclient.DecodeResult, error) {
188+
rProto := &anypb.Any{
189+
TypeUrl: resource.TypeURL,
190+
Value: resource.Value,
191+
}
189192
opts := &DecodeOptions{BootstrapConfig: gd.BootstrapConfig}
190193
if gOpts.ServerConfig != nil {
191194
opts.ServerConfig = gd.ServerConfigMap[*gOpts.ServerConfig]
192195
}
193196

194-
result, err := gd.ResourceType.Decode(opts, raw)
197+
result, err := gd.ResourceType.Decode(opts, rProto)
195198
if result == nil {
196199
return nil, err
197200
}

0 commit comments

Comments
 (0)