xds: Add XdsLbRegistry (#29756)
* xds: Add XdsLbRegistry * Formatting * Fix upb output * Allow alternative type url for Custom LBs * Cleanup * Reviewer comments * Add some comments * Reviewer comments * Reviewer comments * Reviewer comments * Reviewer comments * Fix tests * Fix tests * Fix tests * Fix tests * Fix tests * Unused parameters * Change to make TextFormat usage work internally * Fix namespace qualification errorpull/29862/head
parent
5dc917e1f9
commit
5d9cdc8e67
36 changed files with 1903 additions and 48 deletions
@ -0,0 +1,52 @@ |
||||
/* This file was generated by upbc (the upb compiler) from the input
|
||||
* file: |
||||
* |
||||
* envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.proto |
||||
* |
||||
* Do not edit -- your changes will be discarded when the file is |
||||
* regenerated. */ |
||||
|
||||
#include <stddef.h> |
||||
#include "upb/msg_internal.h" |
||||
#include "envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h" |
||||
#include "google/protobuf/wrappers.upb.h" |
||||
#include "udpa/annotations/status.upb.h" |
||||
#include "validate/validate.upb.h" |
||||
|
||||
#include "upb/port_def.inc" |
||||
|
||||
static const upb_MiniTable_Sub envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_submsgs[3] = { |
||||
{.submsg = &google_protobuf_UInt64Value_msginit}, |
||||
{.submsg = &google_protobuf_UInt64Value_msginit}, |
||||
{.submsg = &google_protobuf_UInt32Value_msginit}, |
||||
}; |
||||
|
||||
static const upb_MiniTable_Field envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash__fields[5] = { |
||||
{1, UPB_SIZE(4, 4), UPB_SIZE(0, 0), kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)}, |
||||
{2, UPB_SIZE(12, 16), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)}, |
||||
{3, UPB_SIZE(16, 24), UPB_SIZE(2, 2), 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)}, |
||||
{4, UPB_SIZE(8, 8), UPB_SIZE(0, 0), kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)}, |
||||
{5, UPB_SIZE(20, 32), UPB_SIZE(3, 3), 2, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)}, |
||||
}; |
||||
|
||||
const upb_MiniTable envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit = { |
||||
&envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_submsgs[0], |
||||
&envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash__fields[0], |
||||
UPB_SIZE(24, 40), 5, kUpb_ExtMode_NonExtendable, 5, 255, 0, |
||||
}; |
||||
|
||||
static const upb_MiniTable *messages_layout[1] = { |
||||
&envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, |
||||
}; |
||||
|
||||
const upb_MiniTable_File envoy_extensions_load_balancing_policies_ring_hash_v3_ring_hash_proto_upb_file_layout = { |
||||
messages_layout, |
||||
NULL, |
||||
NULL, |
||||
1, |
||||
0, |
||||
0, |
||||
}; |
||||
|
||||
#include "upb/port_undef.inc" |
||||
|
@ -0,0 +1,164 @@ |
||||
/* This file was generated by upbc (the upb compiler) from the input
|
||||
* file: |
||||
* |
||||
* envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.proto |
||||
* |
||||
* Do not edit -- your changes will be discarded when the file is |
||||
* regenerated. */ |
||||
|
||||
#ifndef ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_RING_HASH_V3_RING_HASH_PROTO_UPB_H_ |
||||
#define ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_RING_HASH_V3_RING_HASH_PROTO_UPB_H_ |
||||
|
||||
#include "upb/msg_internal.h" |
||||
#include "upb/decode.h" |
||||
#include "upb/decode_fast.h" |
||||
#include "upb/encode.h" |
||||
|
||||
#include "upb/port_def.inc" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
struct envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash; |
||||
typedef struct envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash; |
||||
extern const upb_MiniTable envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit; |
||||
struct google_protobuf_UInt32Value; |
||||
struct google_protobuf_UInt64Value; |
||||
extern const upb_MiniTable google_protobuf_UInt32Value_msginit; |
||||
extern const upb_MiniTable google_protobuf_UInt64Value_msginit; |
||||
|
||||
typedef enum { |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_DEFAULT_HASH = 0, |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_XX_HASH = 1, |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_MURMUR_HASH_2 = 2 |
||||
} envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_HashFunction; |
||||
|
||||
|
||||
|
||||
/* envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash */ |
||||
|
||||
UPB_INLINE envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_new(upb_Arena* arena) { |
||||
return (envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash*)_upb_Message_New(&envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, arena); |
||||
} |
||||
UPB_INLINE envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_parse(const char* buf, size_t size, upb_Arena* arena) { |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* ret = envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_new(arena); |
||||
if (!ret) return NULL; |
||||
if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { |
||||
return NULL; |
||||
} |
||||
return ret; |
||||
} |
||||
UPB_INLINE envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_parse_ex(const char* buf, size_t size, |
||||
const upb_ExtensionRegistry* extreg, |
||||
int options, upb_Arena* arena) { |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* ret = envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_new(arena); |
||||
if (!ret) return NULL; |
||||
if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, extreg, options, arena) != |
||||
kUpb_DecodeStatus_Ok) { |
||||
return NULL; |
||||
} |
||||
return ret; |
||||
} |
||||
UPB_INLINE char* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_serialize(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, upb_Arena* arena, size_t* len) { |
||||
return upb_Encode(msg, &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, 0, arena, len); |
||||
} |
||||
UPB_INLINE char* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_serialize_ex(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, int options, |
||||
upb_Arena* arena, size_t* len) { |
||||
return upb_Encode(msg, &envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_msginit, options, arena, len); |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_hash_function(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
*UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = 0; |
||||
} |
||||
UPB_INLINE int32_t envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_function(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t); |
||||
} |
||||
UPB_INLINE bool envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_has_minimum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
return _upb_hasbit(msg, 1); |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_minimum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
*UPB_PTR_AT(msg, UPB_SIZE(12, 16), const upb_Message*) = NULL; |
||||
} |
||||
UPB_INLINE const struct google_protobuf_UInt64Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_minimum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), const struct google_protobuf_UInt64Value*); |
||||
} |
||||
UPB_INLINE bool envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_has_maximum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
return _upb_hasbit(msg, 2); |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_maximum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
*UPB_PTR_AT(msg, UPB_SIZE(16, 24), const upb_Message*) = NULL; |
||||
} |
||||
UPB_INLINE const struct google_protobuf_UInt64Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_maximum_ring_size(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
return *UPB_PTR_AT(msg, UPB_SIZE(16, 24), const struct google_protobuf_UInt64Value*); |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_use_hostname_for_hashing(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
*UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = 0; |
||||
} |
||||
UPB_INLINE bool envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_use_hostname_for_hashing(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool); |
||||
} |
||||
UPB_INLINE bool envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_has_hash_balance_factor(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
return _upb_hasbit(msg, 3); |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_clear_hash_balance_factor(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
*UPB_PTR_AT(msg, UPB_SIZE(20, 32), const upb_Message*) = NULL; |
||||
} |
||||
UPB_INLINE const struct google_protobuf_UInt32Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_balance_factor(const envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg) { |
||||
return *UPB_PTR_AT(msg, UPB_SIZE(20, 32), const struct google_protobuf_UInt32Value*); |
||||
} |
||||
|
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_hash_function(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, int32_t value) { |
||||
*UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) = value; |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_minimum_ring_size(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, struct google_protobuf_UInt64Value* value) { |
||||
_upb_sethas(msg, 1); |
||||
*UPB_PTR_AT(msg, UPB_SIZE(12, 16), struct google_protobuf_UInt64Value*) = value; |
||||
} |
||||
UPB_INLINE struct google_protobuf_UInt64Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_mutable_minimum_ring_size(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, upb_Arena* arena) { |
||||
struct google_protobuf_UInt64Value* sub = (struct google_protobuf_UInt64Value*)envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_minimum_ring_size(msg); |
||||
if (sub == NULL) { |
||||
sub = (struct google_protobuf_UInt64Value*)_upb_Message_New(&google_protobuf_UInt64Value_msginit, arena); |
||||
if (!sub) return NULL; |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_minimum_ring_size(msg, sub); |
||||
} |
||||
return sub; |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_maximum_ring_size(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, struct google_protobuf_UInt64Value* value) { |
||||
_upb_sethas(msg, 2); |
||||
*UPB_PTR_AT(msg, UPB_SIZE(16, 24), struct google_protobuf_UInt64Value*) = value; |
||||
} |
||||
UPB_INLINE struct google_protobuf_UInt64Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_mutable_maximum_ring_size(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, upb_Arena* arena) { |
||||
struct google_protobuf_UInt64Value* sub = (struct google_protobuf_UInt64Value*)envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_maximum_ring_size(msg); |
||||
if (sub == NULL) { |
||||
sub = (struct google_protobuf_UInt64Value*)_upb_Message_New(&google_protobuf_UInt64Value_msginit, arena); |
||||
if (!sub) return NULL; |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_maximum_ring_size(msg, sub); |
||||
} |
||||
return sub; |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_use_hostname_for_hashing(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, bool value) { |
||||
*UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool) = value; |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_hash_balance_factor(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash *msg, struct google_protobuf_UInt32Value* value) { |
||||
_upb_sethas(msg, 3); |
||||
*UPB_PTR_AT(msg, UPB_SIZE(20, 32), struct google_protobuf_UInt32Value*) = value; |
||||
} |
||||
UPB_INLINE struct google_protobuf_UInt32Value* envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_mutable_hash_balance_factor(envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash* msg, upb_Arena* arena) { |
||||
struct google_protobuf_UInt32Value* sub = (struct google_protobuf_UInt32Value*)envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_balance_factor(msg); |
||||
if (sub == NULL) { |
||||
sub = (struct google_protobuf_UInt32Value*)_upb_Message_New(&google_protobuf_UInt32Value_msginit, arena); |
||||
if (!sub) return NULL; |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_set_hash_balance_factor(msg, sub); |
||||
} |
||||
return sub; |
||||
} |
||||
|
||||
extern const upb_MiniTable_File envoy_extensions_load_balancing_policies_ring_hash_v3_ring_hash_proto_upb_file_layout; |
||||
|
||||
#ifdef __cplusplus |
||||
} /* extern "C" */ |
||||
#endif |
||||
|
||||
#include "upb/port_undef.inc" |
||||
|
||||
#endif /* ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_RING_HASH_V3_RING_HASH_PROTO_UPB_H_ */ |
@ -0,0 +1,46 @@ |
||||
/* This file was generated by upbc (the upb compiler) from the input
|
||||
* file: |
||||
* |
||||
* envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.proto |
||||
* |
||||
* Do not edit -- your changes will be discarded when the file is |
||||
* regenerated. */ |
||||
|
||||
#include <stddef.h> |
||||
#include "upb/msg_internal.h" |
||||
#include "envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h" |
||||
#include "envoy/config/cluster/v3/cluster.upb.h" |
||||
#include "udpa/annotations/status.upb.h" |
||||
#include "validate/validate.upb.h" |
||||
|
||||
#include "upb/port_def.inc" |
||||
|
||||
static const upb_MiniTable_Sub envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_submsgs[1] = { |
||||
{.submsg = &envoy_config_cluster_v3_LoadBalancingPolicy_msginit}, |
||||
}; |
||||
|
||||
static const upb_MiniTable_Field envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality__fields[1] = { |
||||
{1, UPB_SIZE(4, 8), UPB_SIZE(1, 1), 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)}, |
||||
}; |
||||
|
||||
const upb_MiniTable envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit = { |
||||
&envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_submsgs[0], |
||||
&envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality__fields[0], |
||||
UPB_SIZE(8, 24), 1, kUpb_ExtMode_NonExtendable, 1, 255, 0, |
||||
}; |
||||
|
||||
static const upb_MiniTable *messages_layout[1] = { |
||||
&envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, |
||||
}; |
||||
|
||||
const upb_MiniTable_File envoy_extensions_load_balancing_policies_wrr_locality_v3_wrr_locality_proto_upb_file_layout = { |
||||
messages_layout, |
||||
NULL, |
||||
NULL, |
||||
1, |
||||
0, |
||||
0, |
||||
}; |
||||
|
||||
#include "upb/port_undef.inc" |
||||
|
@ -0,0 +1,94 @@ |
||||
/* This file was generated by upbc (the upb compiler) from the input
|
||||
* file: |
||||
* |
||||
* envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.proto |
||||
* |
||||
* Do not edit -- your changes will be discarded when the file is |
||||
* regenerated. */ |
||||
|
||||
#ifndef ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_WRR_LOCALITY_V3_WRR_LOCALITY_PROTO_UPB_H_ |
||||
#define ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_WRR_LOCALITY_V3_WRR_LOCALITY_PROTO_UPB_H_ |
||||
|
||||
#include "upb/msg_internal.h" |
||||
#include "upb/decode.h" |
||||
#include "upb/decode_fast.h" |
||||
#include "upb/encode.h" |
||||
|
||||
#include "upb/port_def.inc" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
struct envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality; |
||||
typedef struct envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality; |
||||
extern const upb_MiniTable envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit; |
||||
struct envoy_config_cluster_v3_LoadBalancingPolicy; |
||||
extern const upb_MiniTable envoy_config_cluster_v3_LoadBalancingPolicy_msginit; |
||||
|
||||
|
||||
|
||||
/* envoy.extensions.load_balancing_policies.wrr_locality.v3.WrrLocality */ |
||||
|
||||
UPB_INLINE envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_new(upb_Arena* arena) { |
||||
return (envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality*)_upb_Message_New(&envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, arena); |
||||
} |
||||
UPB_INLINE envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_parse(const char* buf, size_t size, upb_Arena* arena) { |
||||
envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* ret = envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_new(arena); |
||||
if (!ret) return NULL; |
||||
if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) { |
||||
return NULL; |
||||
} |
||||
return ret; |
||||
} |
||||
UPB_INLINE envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_parse_ex(const char* buf, size_t size, |
||||
const upb_ExtensionRegistry* extreg, |
||||
int options, upb_Arena* arena) { |
||||
envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* ret = envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_new(arena); |
||||
if (!ret) return NULL; |
||||
if (upb_Decode(buf, size, ret, &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, extreg, options, arena) != |
||||
kUpb_DecodeStatus_Ok) { |
||||
return NULL; |
||||
} |
||||
return ret; |
||||
} |
||||
UPB_INLINE char* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_serialize(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg, upb_Arena* arena, size_t* len) { |
||||
return upb_Encode(msg, &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, 0, arena, len); |
||||
} |
||||
UPB_INLINE char* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_serialize_ex(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg, int options, |
||||
upb_Arena* arena, size_t* len) { |
||||
return upb_Encode(msg, &envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_msginit, options, arena, len); |
||||
} |
||||
UPB_INLINE bool envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_has_endpoint_picking_policy(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg) { |
||||
return _upb_hasbit(msg, 1); |
||||
} |
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_clear_endpoint_picking_policy(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg) { |
||||
*UPB_PTR_AT(msg, UPB_SIZE(4, 8), const upb_Message*) = NULL; |
||||
} |
||||
UPB_INLINE const struct envoy_config_cluster_v3_LoadBalancingPolicy* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_endpoint_picking_policy(const envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg) { |
||||
return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), const struct envoy_config_cluster_v3_LoadBalancingPolicy*); |
||||
} |
||||
|
||||
UPB_INLINE void envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_set_endpoint_picking_policy(envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality *msg, struct envoy_config_cluster_v3_LoadBalancingPolicy* value) { |
||||
_upb_sethas(msg, 1); |
||||
*UPB_PTR_AT(msg, UPB_SIZE(4, 8), struct envoy_config_cluster_v3_LoadBalancingPolicy*) = value; |
||||
} |
||||
UPB_INLINE struct envoy_config_cluster_v3_LoadBalancingPolicy* envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_mutable_endpoint_picking_policy(envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality* msg, upb_Arena* arena) { |
||||
struct envoy_config_cluster_v3_LoadBalancingPolicy* sub = (struct envoy_config_cluster_v3_LoadBalancingPolicy*)envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_endpoint_picking_policy(msg); |
||||
if (sub == NULL) { |
||||
sub = (struct envoy_config_cluster_v3_LoadBalancingPolicy*)_upb_Message_New(&envoy_config_cluster_v3_LoadBalancingPolicy_msginit, arena); |
||||
if (!sub) return NULL; |
||||
envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_set_endpoint_picking_policy(msg, sub); |
||||
} |
||||
return sub; |
||||
} |
||||
|
||||
extern const upb_MiniTable_File envoy_extensions_load_balancing_policies_wrr_locality_v3_wrr_locality_proto_upb_file_layout; |
||||
|
||||
#ifdef __cplusplus |
||||
} /* extern "C" */ |
||||
#endif |
||||
|
||||
#include "upb/port_undef.inc" |
||||
|
||||
#endif /* ENVOY_EXTENSIONS_LOAD_BALANCING_POLICIES_WRR_LOCALITY_V3_WRR_LOCALITY_PROTO_UPB_H_ */ |
@ -0,0 +1,291 @@ |
||||
//
|
||||
// Copyright 2022 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include "src/core/ext/xds/xds_lb_policy_registry.h" |
||||
|
||||
#include <stddef.h> |
||||
|
||||
#include <string> |
||||
#include <type_traits> |
||||
#include <utility> |
||||
#include <vector> |
||||
|
||||
#include "absl/memory/memory.h" |
||||
#include "absl/status/status.h" |
||||
#include "absl/strings/str_cat.h" |
||||
#include "absl/strings/str_format.h" |
||||
#include "envoy/config/core/v3/extension.upb.h" |
||||
#include "envoy/extensions/load_balancing_policies/ring_hash/v3/ring_hash.upb.h" |
||||
#include "envoy/extensions/load_balancing_policies/wrr_locality/v3/wrr_locality.upb.h" |
||||
#include "google/protobuf/any.upb.h" |
||||
#include "google/protobuf/struct.upb.h" |
||||
#include "google/protobuf/struct.upbdefs.h" |
||||
#include "google/protobuf/wrappers.upb.h" |
||||
#include "upb/json_encode.h" |
||||
#include "upb/upb.h" |
||||
#include "upb/upb.hpp" |
||||
#include "xds/type/v3/typed_struct.upb.h" |
||||
|
||||
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" |
||||
#include "src/core/ext/xds/upb_utils.h" |
||||
#include "src/core/ext/xds/xds_common_types.h" |
||||
#include "src/core/lib/iomgr/error.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
namespace { |
||||
|
||||
class RingHashLbPolicyConfigFactory |
||||
: public XdsLbPolicyRegistry::ConfigFactory { |
||||
public: |
||||
absl::StatusOr<Json::Object> ConvertXdsLbPolicyConfig( |
||||
const XdsEncodingContext& context, absl::string_view configuration, |
||||
int /* recursion_depth */) override { |
||||
const auto* resource = |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_parse( |
||||
configuration.data(), configuration.size(), context.arena); |
||||
if (resource == nullptr) { |
||||
return absl::InvalidArgumentError( |
||||
"Can't decode RingHash loadbalancing policy"); |
||||
} |
||||
if (envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_hash_function( |
||||
resource) != |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_XX_HASH) { |
||||
return absl::InvalidArgumentError( |
||||
"Invalid hash function provided for RingHash loadbalancing policy. " |
||||
"Only XX_HASH is supported."); |
||||
} |
||||
Json::Object json; |
||||
const auto* min_ring_size = |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_minimum_ring_size( |
||||
resource); |
||||
if (min_ring_size != nullptr) { |
||||
json.emplace("minRingSize", |
||||
google_protobuf_UInt64Value_value(min_ring_size)); |
||||
} |
||||
const auto* max_ring_size = |
||||
envoy_extensions_load_balancing_policies_ring_hash_v3_RingHash_maximum_ring_size( |
||||
resource); |
||||
if (max_ring_size != nullptr) { |
||||
json.emplace("maxRingSize", |
||||
google_protobuf_UInt64Value_value(max_ring_size)); |
||||
} |
||||
return Json::Object{{"ring_hash_experimental", std::move(json)}}; |
||||
} |
||||
|
||||
absl::string_view type() override { return Type(); } |
||||
|
||||
static absl::string_view Type() { |
||||
return "envoy.extensions.load_balancing_policies.ring_hash.v3.RingHash"; |
||||
} |
||||
}; |
||||
|
||||
class RoundRobinLbPolicyConfigFactory |
||||
: public XdsLbPolicyRegistry::ConfigFactory { |
||||
public: |
||||
absl::StatusOr<Json::Object> ConvertXdsLbPolicyConfig( |
||||
const XdsEncodingContext& /* context */, |
||||
absl::string_view /* configuration */, |
||||
int /* recursion_depth */) override { |
||||
return Json::Object{{"round_robin", Json::Object()}}; |
||||
} |
||||
|
||||
absl::string_view type() override { return Type(); } |
||||
|
||||
static absl::string_view Type() { |
||||
return "envoy.extensions.load_balancing_policies.round_robin.v3.RoundRobin"; |
||||
} |
||||
}; |
||||
|
||||
class WrrLocalityLbPolicyConfigFactory |
||||
: public XdsLbPolicyRegistry::ConfigFactory { |
||||
public: |
||||
absl::StatusOr<Json::Object> ConvertXdsLbPolicyConfig( |
||||
const XdsEncodingContext& context, absl::string_view configuration, |
||||
int recursion_depth) override { |
||||
const auto* resource = |
||||
envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_parse( |
||||
configuration.data(), configuration.size(), context.arena); |
||||
if (resource == nullptr) { |
||||
return absl::InvalidArgumentError( |
||||
"Can't decode WrrLocality loadbalancing policy"); |
||||
} |
||||
const auto* endpoint_picking_policy = |
||||
envoy_extensions_load_balancing_policies_wrr_locality_v3_WrrLocality_endpoint_picking_policy( |
||||
resource); |
||||
if (endpoint_picking_policy == nullptr) { |
||||
return absl::InvalidArgumentError( |
||||
"WrrLocality: endpoint_picking_policy not found"); |
||||
} |
||||
auto child_policy = XdsLbPolicyRegistry::ConvertXdsLbPolicyConfig( |
||||
context, endpoint_picking_policy, recursion_depth + 1); |
||||
if (!child_policy.ok()) { |
||||
return absl::InvalidArgumentError( |
||||
absl::StrCat("Error parsing WrrLocality load balancing policy: ", |
||||
child_policy.status().message())); |
||||
} |
||||
return Json::Object{ |
||||
{"xds_wrr_locality_experimental", |
||||
Json::Object{{"child_policy", *std::move(child_policy)}}}}; |
||||
} |
||||
|
||||
absl::string_view type() override { return Type(); } |
||||
|
||||
static absl::string_view Type() { |
||||
return "envoy.extensions.load_balancing_policies.wrr_locality.v3." |
||||
"WrrLocality"; |
||||
} |
||||
}; |
||||
|
||||
absl::StatusOr<Json> ParseStructToJson(const XdsEncodingContext& context, |
||||
const google_protobuf_Struct* resource) { |
||||
upb::Status status; |
||||
const auto* msg_def = google_protobuf_Struct_getmsgdef(context.symtab); |
||||
size_t json_size = upb_JsonEncode(resource, msg_def, context.symtab, 0, |
||||
nullptr, 0, status.ptr()); |
||||
if (json_size == static_cast<size_t>(-1)) { |
||||
return absl::InvalidArgumentError( |
||||
absl::StrCat("Error parsing google::Protobuf::Struct: ", |
||||
upb_Status_ErrorMessage(status.ptr()))); |
||||
} |
||||
void* buf = upb_Arena_Malloc(context.arena, json_size + 1); |
||||
upb_JsonEncode(resource, msg_def, context.symtab, 0, |
||||
reinterpret_cast<char*>(buf), json_size + 1, status.ptr()); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
auto json = Json::Parse(reinterpret_cast<char*>(buf), &error); |
||||
if (error != GRPC_ERROR_NONE) { |
||||
// This should not happen
|
||||
auto ret_status = absl::InternalError( |
||||
absl::StrCat("Error parsing JSON form of google::Protobuf::Struct " |
||||
"produced by upb library: ", |
||||
grpc_error_std_string(error))); |
||||
GRPC_ERROR_UNREF(error); |
||||
return ret_status; |
||||
} |
||||
return json; |
||||
} |
||||
|
||||
} // namespace
|
||||
|
||||
//
|
||||
// XdsLbPolicyRegistry
|
||||
//
|
||||
|
||||
absl::StatusOr<Json::Array> XdsLbPolicyRegistry::ConvertXdsLbPolicyConfig( |
||||
const XdsEncodingContext& context, |
||||
const envoy_config_cluster_v3_LoadBalancingPolicy* lb_policy, |
||||
int recursion_depth) { |
||||
constexpr int kMaxRecursionDepth = 16; |
||||
if (recursion_depth >= kMaxRecursionDepth) { |
||||
return absl::InvalidArgumentError( |
||||
absl::StrFormat("LoadBalancingPolicy configuration has a recursion " |
||||
"depth of more than %d.", |
||||
kMaxRecursionDepth)); |
||||
} |
||||
size_t size = 0; |
||||
const auto* policies = |
||||
envoy_config_cluster_v3_LoadBalancingPolicy_policies(lb_policy, &size); |
||||
for (size_t i = 0; i < size; ++i) { |
||||
absl::StatusOr<Json::Object> policy; |
||||
const auto* typed_extension_config = |
||||
envoy_config_cluster_v3_LoadBalancingPolicy_Policy_typed_extension_config( |
||||
policies[i]); |
||||
if (typed_extension_config == nullptr) { |
||||
return absl::InvalidArgumentError( |
||||
"Error parsing LoadBalancingPolicy::Policy - Missing " |
||||
"typed_extension_config field"); |
||||
} |
||||
const auto* typed_config = |
||||
envoy_config_core_v3_TypedExtensionConfig_typed_config( |
||||
typed_extension_config); |
||||
if (typed_config == nullptr) { |
||||
return absl::InvalidArgumentError( |
||||
"Error parsing LoadBalancingPolicy::Policy - Missing " |
||||
"TypedExtensionConfig::typed_config field"); |
||||
} |
||||
auto type = ExtractExtensionTypeName(context, typed_config); |
||||
if (!type.ok()) { |
||||
return absl::InvalidArgumentError(absl::StrCat( |
||||
"Error parsing " |
||||
"LoadBalancingPolicy::Policy::TypedExtensionConfig::typed_config: ", |
||||
type.status().message())); |
||||
} |
||||
absl::string_view value = |
||||
UpbStringToAbsl(google_protobuf_Any_value(typed_config)); |
||||
auto config_factory_it = Get()->policy_config_factories_.find(type->type); |
||||
if (config_factory_it != Get()->policy_config_factories_.end()) { |
||||
policy = config_factory_it->second->ConvertXdsLbPolicyConfig( |
||||
context, value, recursion_depth); |
||||
if (!policy.ok()) { |
||||
return absl::InvalidArgumentError( |
||||
absl::StrCat("Error parsing " |
||||
"LoadBalancingPolicy::Policy::TypedExtensionConfig::" |
||||
"typed_config to JSON: ", |
||||
policy.status().message())); |
||||
} |
||||
} else if (type->typed_struct != nullptr) { |
||||
// Custom lb policy config
|
||||
std::string custom_type = std::string(type->type); |
||||
if (!LoadBalancingPolicyRegistry::LoadBalancingPolicyExists( |
||||
custom_type.c_str(), nullptr)) { |
||||
// Skip unsupported custom lb policy.
|
||||
continue; |
||||
} |
||||
// Convert typed struct to json.
|
||||
auto value = xds_type_v3_TypedStruct_value(type->typed_struct); |
||||
if (value == nullptr) { |
||||
policy = Json::Object{{std::move(custom_type), Json() /* null */}}; |
||||
} else { |
||||
auto parsed_value = ParseStructToJson(context, value); |
||||
if (!parsed_value.ok()) { |
||||
return absl::InvalidArgumentError(absl::StrCat( |
||||
"Error parsing LoadBalancingPolicy: Custom Policy: ", custom_type, |
||||
": ", parsed_value.status().message())); |
||||
} |
||||
policy = |
||||
Json::Object{{std::move(custom_type), *(std::move(parsed_value))}}; |
||||
} |
||||
} else { |
||||
// Unsupported type. Skipping entry.
|
||||
continue; |
||||
} |
||||
return Json::Array{std::move(policy.value())}; |
||||
} |
||||
return absl::InvalidArgumentError( |
||||
"No supported load balancing policy config found."); |
||||
} |
||||
|
||||
XdsLbPolicyRegistry::XdsLbPolicyRegistry() { |
||||
policy_config_factories_.emplace( |
||||
RingHashLbPolicyConfigFactory::Type(), |
||||
absl::make_unique<RingHashLbPolicyConfigFactory>()); |
||||
policy_config_factories_.emplace( |
||||
RoundRobinLbPolicyConfigFactory::Type(), |
||||
absl::make_unique<RoundRobinLbPolicyConfigFactory>()); |
||||
policy_config_factories_.emplace( |
||||
WrrLocalityLbPolicyConfigFactory::Type(), |
||||
absl::make_unique<WrrLocalityLbPolicyConfigFactory>()); |
||||
} |
||||
|
||||
XdsLbPolicyRegistry* XdsLbPolicyRegistry::Get() { |
||||
// This is thread-safe since C++11
|
||||
static XdsLbPolicyRegistry* instance = new XdsLbPolicyRegistry(); |
||||
return instance; |
||||
} |
||||
|
||||
} // namespace grpc_core
|
@ -0,0 +1,72 @@ |
||||
//
|
||||
// Copyright 2022 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
#ifndef GRPC_CORE_EXT_XDS_XDS_LB_POLICY_REGISTRY_H |
||||
#define GRPC_CORE_EXT_XDS_XDS_LB_POLICY_REGISTRY_H |
||||
|
||||
#include <grpc/support/port_platform.h> |
||||
|
||||
#include <map> |
||||
#include <memory> |
||||
|
||||
#include "absl/status/statusor.h" |
||||
#include "absl/strings/string_view.h" |
||||
#include "envoy/config/cluster/v3/cluster.upb.h" |
||||
|
||||
#include "src/core/ext/xds/upb_utils.h" |
||||
#include "src/core/lib/json/json.h" |
||||
|
||||
namespace grpc_core { |
||||
|
||||
// A registry that maintans a set of converters that are able to map xDS
|
||||
// loadbalancing policy configurations to gRPC's JSON format.
|
||||
class XdsLbPolicyRegistry { |
||||
public: |
||||
class ConfigFactory { |
||||
public: |
||||
virtual ~ConfigFactory() {} |
||||
virtual absl::StatusOr<Json::Object> ConvertXdsLbPolicyConfig( |
||||
const XdsEncodingContext& context, absl::string_view configuration, |
||||
int recursion_depth) = 0; |
||||
|
||||
virtual absl::string_view type() = 0; |
||||
}; |
||||
|
||||
// Converts an xDS cluster load balancing policy message to gRPC's JSON
|
||||
// format. An error is returned if none of the lb policies in the list are
|
||||
// supported, or if a supported lb policy configuration conversion fails. \a
|
||||
// recursion_depth indicates the current depth of the tree if lb_policy
|
||||
// configuration recursively holds other lb policies.
|
||||
static absl::StatusOr<Json::Array> ConvertXdsLbPolicyConfig( |
||||
const XdsEncodingContext& context, |
||||
const envoy_config_cluster_v3_LoadBalancingPolicy* lb_policy, |
||||
int recursion_depth = 0); |
||||
|
||||
private: |
||||
XdsLbPolicyRegistry(); |
||||
|
||||
static XdsLbPolicyRegistry* Get(); |
||||
|
||||
// A map of config factories that goes from the type of the lb policy config
|
||||
// to the config factory.
|
||||
std::map<absl::string_view /* Owned by ConfigFactory */, |
||||
std::unique_ptr<ConfigFactory>> |
||||
policy_config_factories_; |
||||
}; |
||||
|
||||
} // namespace grpc_core
|
||||
|
||||
#endif // GRPC_CORE_EXT_XDS_XDS_LB_POLICY_REGISTRY_H
|
@ -0,0 +1,59 @@ |
||||
// Copyright 2022 The gRPC Authors |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
|
||||
// Local copy of Envoy xDS proto file, used for testing only. |
||||
|
||||
syntax = "proto3"; |
||||
|
||||
package envoy.extensions.load_balancing_policies.ring_hash.v3; |
||||
|
||||
import "google/protobuf/wrappers.proto"; |
||||
|
||||
// [#protodoc-title: Ring Hash Load Balancing Policy] |
||||
|
||||
// This configuration allows the built-in RING_HASH LB policy to be configured via the LB policy |
||||
// extension point. See the :ref:`load balancing architecture overview |
||||
// <arch_overview_load_balancing_types>` for more information. |
||||
// [#extension: envoy.clusters.lb_policy] |
||||
// [#next-free-field: 6] |
||||
message RingHash { |
||||
// The hash function used to hash hosts onto the ketama ring. |
||||
enum HashFunction { |
||||
// Currently defaults to XX_HASH. |
||||
DEFAULT_HASH = 0; |
||||
|
||||
// Use `xxHash <https://github.com/Cyan4973/xxHash>`_. |
||||
XX_HASH = 1; |
||||
|
||||
// Use `MurmurHash2 <https://sites.google.com/site/murmurhash/>`_, this is compatible with |
||||
// std:hash<string> in GNU libstdc++ 3.4.20 or above. This is typically the case when compiled |
||||
// on Linux and not macOS. |
||||
MURMUR_HASH_2 = 2; |
||||
} |
||||
|
||||
// The hash function used to hash hosts onto the ketama ring. The value defaults to |
||||
// :ref:`XX_HASH<envoy_v3_api_enum_value_config.cluster.v3.Cluster.RingHashLbConfig.HashFunction.XX_HASH>`. |
||||
HashFunction hash_function = 1; |
||||
|
||||
// Minimum hash ring size. The larger the ring is (that is, the more hashes there are for each |
||||
// provided host) the better the request distribution will reflect the desired weights. Defaults |
||||
// to 1024 entries, and limited to 8M entries. See also |
||||
// :ref:`maximum_ring_size<envoy_v3_api_field_config.cluster.v3.Cluster.RingHashLbConfig.maximum_ring_size>`. |
||||
google.protobuf.UInt64Value minimum_ring_size = 2; |
||||
|
||||
// Maximum hash ring size. Defaults to 8M entries, and limited to 8M entries, but can be lowered |
||||
// to further constrain resource use. See also |
||||
// :ref:`minimum_ring_size<envoy_v3_api_field_config.cluster.v3.Cluster.RingHashLbConfig.minimum_ring_size>`. |
||||
google.protobuf.UInt64Value maximum_ring_size = 3; |
||||
} |
@ -0,0 +1,28 @@ |
||||
// Copyright 2022 The gRPC Authors |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
|
||||
// Local copy of Envoy xDS proto file, used for testing only. |
||||
|
||||
syntax = "proto3"; |
||||
|
||||
package envoy.extensions.load_balancing_policies.round_robin.v3; |
||||
|
||||
// [#protodoc-title: Round Robin Load Balancing Policy] |
||||
|
||||
// This configuration allows the built-in ROUND_ROBIN LB policy to be configured via the LB policy |
||||
// extension point. See the :ref:`load balancing architecture overview |
||||
// <arch_overview_load_balancing_types>` for more information. |
||||
// [#extension: envoy.clusters.lb_policy] |
||||
message RoundRobin { |
||||
} |
@ -0,0 +1,53 @@ |
||||
// Copyright 2022 The gRPC Authors |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
|
||||
// Local copy of xDS proto file, used for testing only. |
||||
|
||||
syntax = "proto3"; |
||||
|
||||
package xds.type.v3; |
||||
|
||||
import "google/protobuf/struct.proto"; |
||||
|
||||
// A TypedStruct contains an arbitrary JSON serialized protocol buffer message with a URL that |
||||
// describes the type of the serialized message. This is very similar to google.protobuf.Any, |
||||
// instead of having protocol buffer binary, this employs google.protobuf.Struct as value. |
||||
// |
||||
// This message is intended to be embedded inside Any, so it shouldn't be directly referred |
||||
// from other UDPA messages. |
||||
// |
||||
// When packing an opaque extension config, packing the expected type into Any is preferred |
||||
// wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor |
||||
// is not available, for example if: |
||||
// - A control plane sends opaque message that is originally from external source in human readable |
||||
// format such as JSON or YAML. |
||||
// - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot |
||||
// serialize the message in protocol buffer binary format. |
||||
// - The DPLB doesn't have have the knowledge of the protocol buffer schema its plugin or extension |
||||
// uses. This has to be indicated in the DPLB capability negotiation. |
||||
// |
||||
// When a DPLB receives a TypedStruct in Any, it should: |
||||
// - Check if the type_url of the TypedStruct matches the type the extension expects. |
||||
// - Convert value to the type described in type_url and perform validation. |
||||
// TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link |
||||
// protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions). |
||||
message TypedStruct { |
||||
// A URL that uniquely identifies the type of the serialize protocol buffer message. |
||||
// This has same semantics and format described in google.protobuf.Any: |
||||
// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto |
||||
string type_url = 1; |
||||
|
||||
// A JSON representation of the above specified type. |
||||
google.protobuf.Struct value = 2; |
||||
} |
@ -0,0 +1,53 @@ |
||||
// Copyright 2022 The gRPC Authors |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
|
||||
// Local copy of xDS proto file, used for testing only. |
||||
|
||||
syntax = "proto3"; |
||||
|
||||
package udpa.type.v1; |
||||
|
||||
import "google/protobuf/struct.proto"; |
||||
|
||||
// A TypedStruct contains an arbitrary JSON serialized protocol buffer message with a URL that |
||||
// describes the type of the serialized message. This is very similar to google.protobuf.Any, |
||||
// instead of having protocol buffer binary, this employs google.protobuf.Struct as value. |
||||
// |
||||
// This message is intended to be embedded inside Any, so it shouldn't be directly referred |
||||
// from other UDPA messages. |
||||
// |
||||
// When packing an opaque extension config, packing the expected type into Any is preferred |
||||
// wherever possible for its efficiency. TypedStruct should be used only if a proto descriptor |
||||
// is not available, for example if: |
||||
// - A control plane sends opaque message that is originally from external source in human readable |
||||
// format such as JSON or YAML. |
||||
// - The control plane doesn't have the knowledge of the protocol buffer schema hence it cannot |
||||
// serialize the message in protocol buffer binary format. |
||||
// - The DPLB doesn't have have the knowledge of the protocol buffer schema its plugin or extension |
||||
// uses. This has to be indicated in the DPLB capability negotiation. |
||||
// |
||||
// When a DPLB receives a TypedStruct in Any, it should: |
||||
// - Check if the type_url of the TypedStruct matches the type the extension expects. |
||||
// - Convert value to the type described in type_url and perform validation. |
||||
// TODO(lizan): Figure out how TypeStruct should be used with DPLB extensions that doesn't link |
||||
// protobuf descriptor with DPLB itself, (e.g. gRPC LB Plugin, Envoy WASM extensions). |
||||
message TypedStruct { |
||||
// A URL that uniquely identifies the type of the serialize protocol buffer message. |
||||
// This has same semantics and format described in google.protobuf.Any: |
||||
// https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/any.proto |
||||
string type_url = 1; |
||||
|
||||
// A JSON representation of the above specified type. |
||||
google.protobuf.Struct value = 2; |
||||
} |
@ -0,0 +1,31 @@ |
||||
// Copyright 2022 The gRPC Authors |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
|
||||
// Local copy of Envoy xDS proto file, used for testing only. |
||||
|
||||
syntax = "proto3"; |
||||
|
||||
package envoy.extensions.load_balancing_policies.wrr_locality.v3; |
||||
|
||||
import "src/proto/grpc/testing/xds/v3/cluster.proto"; |
||||
|
||||
// [#protodoc-title: Weighted Round Robin Locality-Picking Load Balancing Policy] |
||||
|
||||
// Configuration for the wrr_locality LB policy. See the :ref:`load balancing architecture overview |
||||
// <arch_overview_load_balancing_types>` for more information. |
||||
// [#extension: envoy.clusters.lb_policy] |
||||
message WrrLocality { |
||||
// The child LB policy to create for endpoint-picking within the chosen locality. |
||||
config.cluster.v3.LoadBalancingPolicy endpoint_picking_policy = 1; |
||||
} |
@ -0,0 +1,534 @@ |
||||
//
|
||||
//
|
||||
// Copyright 2022 gRPC authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
//
|
||||
|
||||
#include "src/core/ext/xds/xds_lb_policy_registry.h" |
||||
|
||||
#include <gmock/gmock.h> |
||||
#include <gtest/gtest.h> |
||||
|
||||
#include "absl/strings/str_format.h" |
||||
#include "upb/def.hpp" |
||||
#include "upb/upb.h" |
||||
#include "upb/upb.hpp" |
||||
|
||||
#include <grpc/grpc.h> |
||||
|
||||
#include "src/core/ext/filters/client_channel/lb_policy_factory.h" |
||||
#include "src/core/ext/filters/client_channel/lb_policy_registry.h" |
||||
#include "src/proto/grpc/testing/xds/v3/cluster.grpc.pb.h" |
||||
#include "src/proto/grpc/testing/xds/v3/ring_hash.grpc.pb.h" |
||||
#include "src/proto/grpc/testing/xds/v3/round_robin.grpc.pb.h" |
||||
#include "src/proto/grpc/testing/xds/v3/typed_struct.grpc.pb.h" |
||||
#include "src/proto/grpc/testing/xds/v3/udpa_typed_struct.grpc.pb.h" |
||||
#include "src/proto/grpc/testing/xds/v3/wrr_locality.grpc.pb.h" |
||||
#include "test/core/util/test_config.h" |
||||
#include "test/cpp/util/config_grpc_cli.h" |
||||
|
||||
namespace grpc_core { |
||||
namespace testing { |
||||
namespace { |
||||
|
||||
using LoadBalancingPolicyProto = |
||||
::envoy::config::cluster::v3::LoadBalancingPolicy; |
||||
using ::envoy::extensions::load_balancing_policies::ring_hash::v3::RingHash; |
||||
using ::envoy::extensions::load_balancing_policies::round_robin::v3::RoundRobin; |
||||
using ::envoy::extensions::load_balancing_policies::wrr_locality::v3:: |
||||
WrrLocality; |
||||
using ::xds::type::v3::TypedStruct; |
||||
|
||||
// Uses XdsLbPolicyRegistry to convert
|
||||
// envoy::config::cluster::v3::LoadBalancingPolicy to gRPC's JSON form.
|
||||
absl::StatusOr<Json::Array> ConvertXdsPolicy(LoadBalancingPolicyProto policy) { |
||||
std::string serialized_policy = policy.SerializeAsString(); |
||||
upb::Arena arena; |
||||
upb::SymbolTable symtab; |
||||
XdsEncodingContext context = {nullptr, XdsBootstrap::XdsServer(), |
||||
nullptr, symtab.ptr(), |
||||
arena.ptr(), true, |
||||
nullptr}; |
||||
auto* upb_policy = envoy_config_cluster_v3_LoadBalancingPolicy_parse( |
||||
serialized_policy.data(), serialized_policy.size(), arena.ptr()); |
||||
return XdsLbPolicyRegistry::ConvertXdsLbPolicyConfig(context, upb_policy); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, EmptyLoadBalancingPolicy) { |
||||
auto result = ConvertXdsPolicy(LoadBalancingPolicyProto()); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT( |
||||
std::string(result.status().message()), |
||||
::testing::HasSubstr("No supported load balancing policy config found")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, UnsupportedBuiltinType) { |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
LoadBalancingPolicyProto()); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT( |
||||
std::string(result.status().message()), |
||||
::testing::HasSubstr("No supported load balancing policy config found")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, MissingTypedExtensionConfig) { |
||||
LoadBalancingPolicyProto policy; |
||||
policy.add_policies(); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT(std::string(result.status().message()), |
||||
::testing::HasSubstr("Error parsing LoadBalancingPolicy::Policy " |
||||
"- Missing typed_extension_config field")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, MissingTypedConfig) { |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config(); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT( |
||||
std::string(result.status().message()), |
||||
::testing::HasSubstr("Error parsing LoadBalancingPolicy::Policy - " |
||||
"Missing TypedExtensionConfig::typed_config field")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, RingHashInvalidHash) { |
||||
RingHash ring_hash; |
||||
ring_hash.set_hash_function(RingHash::DEFAULT_HASH); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
ring_hash); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT( |
||||
std::string(result.status().message()), |
||||
::testing::HasSubstr("Invalid hash function provided for RingHash " |
||||
"loadbalancing policy. Only XX_HASH is supported")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, RingHashRingSizeDefaults) { |
||||
RingHash ring_hash; |
||||
ring_hash.set_hash_function(RingHash::XX_HASH); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
ring_hash); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse("{" |
||||
"\"ring_hash_experimental\": {" |
||||
"}}", |
||||
&error)); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, RingHashRingSizeCustom) { |
||||
RingHash ring_hash; |
||||
ring_hash.set_hash_function(RingHash::XX_HASH); |
||||
ring_hash.mutable_minimum_ring_size()->set_value(1234); |
||||
ring_hash.mutable_maximum_ring_size()->set_value(4567); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
ring_hash); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse("{" |
||||
"\"ring_hash_experimental\": {" |
||||
" \"minRingSize\": 1234," |
||||
" \"maxRingSize\": 4567" |
||||
"}}", |
||||
&error)); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, RoundRobin) { |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
RoundRobin()); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse("{" |
||||
"\"round_robin\": {}" |
||||
"}", |
||||
&error)); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, WrrLocality) { |
||||
WrrLocality wrr_locality; |
||||
wrr_locality.mutable_endpoint_picking_policy() |
||||
->add_policies() |
||||
->mutable_typed_extension_config() |
||||
->mutable_typed_config() |
||||
->PackFrom(RoundRobin()); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
wrr_locality); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse("{" |
||||
"\"xds_wrr_locality_experimental\": {" |
||||
" \"child_policy\": [{" |
||||
" \"round_robin\": {}" |
||||
" }]" |
||||
"}}", |
||||
&error)); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, WrrLocalityMissingEndpointPickingPolicy) { |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
WrrLocality()); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT(std::string(result.status().message()), |
||||
::testing::ContainsRegex( |
||||
"Error parsing LoadBalancingPolicy.*WrrLocality: " |
||||
"endpoint_picking_policy not found")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, WrrLocalityChildPolicyError) { |
||||
WrrLocality wrr_locality; |
||||
wrr_locality.mutable_endpoint_picking_policy() |
||||
->add_policies() |
||||
->mutable_typed_extension_config() |
||||
->mutable_typed_config() |
||||
->PackFrom(RingHash()); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
wrr_locality); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT(std::string(result.status().message()), |
||||
::testing::ContainsRegex( |
||||
"Error parsing LoadBalancingPolicy.*Error parsing " |
||||
"WrrLocality load balancing policy.*Error parsing " |
||||
"LoadBalancingPolicy.*Invalid hash function provided for " |
||||
"RingHash loadbalancing policy. Only XX_HASH is supported.")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, WrrLocalityUnsupportedTypeSkipped) { |
||||
// Create WrrLocality policy and add two policies to its list, an unsupported
|
||||
// type and then a known RoundRobin type. Expect that the unsupported type is
|
||||
// skipped and RoundRobin is selected.
|
||||
WrrLocality wrr_locality; |
||||
wrr_locality.mutable_endpoint_picking_policy() |
||||
->add_policies() |
||||
->mutable_typed_extension_config() |
||||
->mutable_typed_config() |
||||
->PackFrom(LoadBalancingPolicyProto()); |
||||
wrr_locality.mutable_endpoint_picking_policy() |
||||
->add_policies() |
||||
->mutable_typed_extension_config() |
||||
->mutable_typed_config() |
||||
->PackFrom(RoundRobin()); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
wrr_locality); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse("{" |
||||
"\"xds_wrr_locality_experimental\": {" |
||||
" \"child_policy\": [{" |
||||
" \"round_robin\": {}" |
||||
" }]" |
||||
"}}", |
||||
&error)); |
||||
} |
||||
|
||||
class CustomLbPolicyFactory : public LoadBalancingPolicyFactory { |
||||
public: |
||||
OrphanablePtr<LoadBalancingPolicy> CreateLoadBalancingPolicy( |
||||
LoadBalancingPolicy::Args /* args */) const override { |
||||
GPR_ASSERT(false); |
||||
return nullptr; |
||||
} |
||||
|
||||
const char* name() const override { return "test.CustomLb"; } |
||||
|
||||
RefCountedPtr<LoadBalancingPolicy::Config> ParseLoadBalancingConfig( |
||||
const Json& /* json */, grpc_error_handle* /* error */) const override { |
||||
return nullptr; |
||||
} |
||||
}; |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, CustomLbPolicy) { |
||||
TypedStruct typed_struct; |
||||
typed_struct.set_type_url("type.googleapis.com/test.CustomLb"); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
typed_struct); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse("{" |
||||
"\"test.CustomLb\": null}", |
||||
&error)); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, CustomLbPolicyUdpaTyped) { |
||||
::udpa::type::v1::TypedStruct typed_struct; |
||||
typed_struct.set_type_url("type.googleapis.com/test.CustomLb"); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
typed_struct); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse("{" |
||||
"\"test.CustomLb\": null}", |
||||
&error)); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, UnsupportedCustomTypeError) { |
||||
TypedStruct typed_struct; |
||||
typed_struct.set_type_url("myorg/foo/bar/test.UnknownLb"); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
typed_struct); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT( |
||||
std::string(result.status().message()), |
||||
::testing::HasSubstr("No supported load balancing policy config found")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, CustomTypeInvalidUrlMissingSlash) { |
||||
TypedStruct typed_struct; |
||||
typed_struct.set_type_url("test.UnknownLb"); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
typed_struct); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT( |
||||
std::string(result.status().message()), |
||||
::testing::HasSubstr("Error parsing " |
||||
"LoadBalancingPolicy::Policy::TypedExtensionConfig::" |
||||
"typed_config: Invalid type_url test.UnknownLb")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, CustomTypeInvalidUrlEmptyType) { |
||||
TypedStruct typed_struct; |
||||
typed_struct.set_type_url("myorg/"); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
typed_struct); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT( |
||||
std::string(result.status().message()), |
||||
::testing::HasSubstr("Error parsing " |
||||
"LoadBalancingPolicy::Policy::TypedExtensionConfig::" |
||||
"typed_config: Invalid type_url myorg/")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, CustomLbPolicyJsonConversion) { |
||||
TypedStruct typed_struct; |
||||
ASSERT_TRUE(grpc::protobuf::TextFormat::ParseFromString( |
||||
R"pb( |
||||
type_url: "type.googleapis.com/test.CustomLb" |
||||
value { |
||||
fields { |
||||
key: "key" |
||||
value { null_value: NULL_VALUE } |
||||
} |
||||
fields { |
||||
key: "number" |
||||
value { number_value: 123 } |
||||
} |
||||
fields { |
||||
key: "string" |
||||
value { string_value: "value" } |
||||
} |
||||
fields { |
||||
key: "struct" |
||||
value { |
||||
struct_value { |
||||
fields { |
||||
key: "key" |
||||
value { null_value: NULL_VALUE } |
||||
} |
||||
} |
||||
} |
||||
} |
||||
fields { |
||||
key: "list" |
||||
value { |
||||
list_value { |
||||
values { null_value: NULL_VALUE } |
||||
values { number_value: 234 } |
||||
} |
||||
} |
||||
} |
||||
} |
||||
)pb", |
||||
&typed_struct)); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
typed_struct); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse( |
||||
R"json({ |
||||
"test.CustomLb":{ |
||||
"key": null, |
||||
"number": 123, |
||||
"string": "value", |
||||
"struct": { |
||||
"key": null |
||||
}, |
||||
"list": [null, 234] |
||||
} |
||||
})json", |
||||
&error)); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, CustomLbPolicyListError) { |
||||
TypedStruct typed_struct; |
||||
typed_struct.set_type_url("type.googleapis.com/test.CustomLb"); |
||||
auto* fields = typed_struct.mutable_value()->mutable_fields(); |
||||
google::protobuf::Value value; |
||||
value.mutable_list_value()->add_values(); |
||||
(*fields)["key"] = value; |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
typed_struct); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT(std::string(result.status().message()), |
||||
::testing::HasSubstr( |
||||
"Error parsing LoadBalancingPolicy: Custom Policy: " |
||||
"test.CustomLb: Error parsing google::Protobuf::Struct: No " |
||||
"value set in Value proto")); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, UnsupportedBuiltInTypeSkipped) { |
||||
// Add two policies to list, an unsupported type and then a known RoundRobin
|
||||
// type. Expect that the unsupported type is skipped and RoundRobin is
|
||||
// selected.
|
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
LoadBalancingPolicyProto()); |
||||
lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
RoundRobin()); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse("{" |
||||
"\"round_robin\": {}" |
||||
"}", |
||||
&error)); |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, UnsupportedCustomTypeSkipped) { |
||||
// Add two policies to list, an unsupported custom type and then a known
|
||||
// RoundRobin type. Expect that the unsupported type is skipped and RoundRobin
|
||||
// is selected.
|
||||
TypedStruct typed_struct; |
||||
typed_struct.set_type_url("myorg/foo/bar/test.UnknownLb"); |
||||
LoadBalancingPolicyProto policy; |
||||
auto* lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
typed_struct); |
||||
lb_policy = policy.add_policies(); |
||||
lb_policy->mutable_typed_extension_config()->mutable_typed_config()->PackFrom( |
||||
RoundRobin()); |
||||
auto result = ConvertXdsPolicy(policy); |
||||
EXPECT_TRUE(result.ok()); |
||||
EXPECT_EQ(result->size(), 1); |
||||
grpc_error_handle error = GRPC_ERROR_NONE; |
||||
EXPECT_EQ((*result)[0], Json::Parse("{" |
||||
"\"round_robin\": {}" |
||||
"}", |
||||
&error)); |
||||
} |
||||
|
||||
// Build a recurse load balancing policy that goes beyond the max allowable
|
||||
// depth of 16.
|
||||
LoadBalancingPolicyProto BuildRecursiveLoadBalancingPolicy(int depth) { |
||||
LoadBalancingPolicyProto policy; |
||||
if (depth >= 16) { |
||||
policy.add_policies() |
||||
->mutable_typed_extension_config() |
||||
->mutable_typed_config() |
||||
->PackFrom(RoundRobin()); |
||||
return policy; |
||||
} |
||||
WrrLocality wrr_locality; |
||||
*wrr_locality.mutable_endpoint_picking_policy() = |
||||
BuildRecursiveLoadBalancingPolicy(depth + 1); |
||||
policy.add_policies() |
||||
->mutable_typed_extension_config() |
||||
->mutable_typed_config() |
||||
->PackFrom(wrr_locality); |
||||
return policy; |
||||
} |
||||
|
||||
TEST(XdsLbPolicyRegistryTest, MaxRecursion) { |
||||
auto result = ConvertXdsPolicy(BuildRecursiveLoadBalancingPolicy(0)); |
||||
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument); |
||||
EXPECT_THAT(std::string(result.status().message()), |
||||
::testing::ContainsRegex("LoadBalancingPolicy configuration has " |
||||
"a recursion depth of more than 16")); |
||||
} |
||||
|
||||
} // namespace
|
||||
} // namespace testing
|
||||
} // namespace grpc_core
|
||||
|
||||
int main(int argc, char** argv) { |
||||
::testing::InitGoogleTest(&argc, argv); |
||||
grpc::testing::TestEnvironment env(&argc, argv); |
||||
grpc_core::LoadBalancingPolicyRegistry::Builder:: |
||||
RegisterLoadBalancingPolicyFactory( |
||||
absl::make_unique<grpc_core::testing::CustomLbPolicyFactory>()); |
||||
grpc_init(); |
||||
auto result = RUN_ALL_TESTS(); |
||||
grpc_shutdown(); |
||||
return result; |
||||
} |
Loading…
Reference in new issue