Merge pull request #14917 from hashicorp/dans/NET-718/peering-outbound-mesh-gateway-xds
This commit is contained in:
commit
92d0231f5a
|
@ -4238,6 +4238,7 @@ func (a *Agent) registerCache() {
|
|||
a.cache.RegisterType(cachetype.CompiledDiscoveryChainName, &cachetype.CompiledDiscoveryChain{RPC: a})
|
||||
|
||||
a.cache.RegisterType(cachetype.GatewayServicesName, &cachetype.GatewayServices{RPC: a})
|
||||
|
||||
a.cache.RegisterType(cachetype.ServiceGatewaysName, &cachetype.ServiceGateways{RPC: a})
|
||||
|
||||
a.cache.RegisterType(cachetype.ConfigEntryListName, &cachetype.ConfigEntryList{RPC: a})
|
||||
|
@ -4257,6 +4258,8 @@ func (a *Agent) registerCache() {
|
|||
|
||||
a.cache.RegisterType(cachetype.PeeredUpstreamsName, &cachetype.PeeredUpstreams{RPC: a})
|
||||
|
||||
a.cache.RegisterType(cachetype.PeeringListName, &cachetype.Peerings{Client: a.rpcClientPeering})
|
||||
|
||||
a.registerEntCache()
|
||||
}
|
||||
|
||||
|
@ -4371,6 +4374,7 @@ func (a *Agent) proxyDataSources() proxycfg.DataSources {
|
|||
InternalServiceDump: proxycfgglue.CacheInternalServiceDump(a.cache),
|
||||
LeafCertificate: proxycfgglue.CacheLeafCertificate(a.cache),
|
||||
PeeredUpstreams: proxycfgglue.CachePeeredUpstreams(a.cache),
|
||||
PeeringList: proxycfgglue.CachePeeringList(a.cache),
|
||||
PreparedQuery: proxycfgglue.CachePrepraredQuery(a.cache),
|
||||
ResolvedServiceConfig: proxycfgglue.CacheResolvedServiceConfig(a.cache),
|
||||
ServiceList: proxycfgglue.CacheServiceList(a.cache),
|
||||
|
@ -4399,6 +4403,7 @@ func (a *Agent) proxyDataSources() proxycfg.DataSources {
|
|||
sources.IntentionUpstreams = proxycfgglue.ServerIntentionUpstreams(deps)
|
||||
sources.IntentionUpstreamsDestination = proxycfgglue.ServerIntentionUpstreamsDestination(deps)
|
||||
sources.InternalServiceDump = proxycfgglue.ServerInternalServiceDump(deps, proxycfgglue.CacheInternalServiceDump(a.cache))
|
||||
sources.PeeringList = proxycfgglue.ServerPeeringList(deps)
|
||||
sources.PeeredUpstreams = proxycfgglue.ServerPeeredUpstreams(deps)
|
||||
sources.ResolvedServiceConfig = proxycfgglue.ServerResolvedServiceConfig(deps, proxycfgglue.CacheResolvedServiceConfig(a.cache))
|
||||
sources.ServiceList = proxycfgglue.ServerServiceList(deps, proxycfgglue.CacheServiceList(a.cache))
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
// Code generated by mockery v2.14.0. DO NOT EDIT.
|
||||
|
||||
package cachetype
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
grpc "google.golang.org/grpc"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
pbpeering "github.com/hashicorp/consul/proto/pbpeering"
|
||||
)
|
||||
|
||||
// MockPeeringLister is an autogenerated mock type for the PeeringLister type
|
||||
type MockPeeringLister struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// PeeringList provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *MockPeeringLister) PeeringList(ctx context.Context, in *pbpeering.PeeringListRequest, opts ...grpc.CallOption) (*pbpeering.PeeringListResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
for _i := range opts {
|
||||
_va[_i] = opts[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, ctx, in)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
var r0 *pbpeering.PeeringListResponse
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *pbpeering.PeeringListRequest, ...grpc.CallOption) *pbpeering.PeeringListResponse); ok {
|
||||
r0 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*pbpeering.PeeringListResponse)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *pbpeering.PeeringListRequest, ...grpc.CallOption) error); ok {
|
||||
r1 = rf(ctx, in, opts...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewMockPeeringLister interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}
|
||||
|
||||
// NewMockPeeringLister creates a new instance of MockPeeringLister. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewMockPeeringLister(t mockConstructorTestingTNewMockPeeringLister) *MockPeeringLister {
|
||||
mock := &MockPeeringLister{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package cachetype
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
external "github.com/hashicorp/consul/agent/grpc-external"
|
||||
"github.com/hashicorp/consul/proto/pbpeering"
|
||||
"github.com/mitchellh/hashstructure"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
)
|
||||
|
||||
// PeeringListName is the recommended name for registration.
|
||||
const PeeringListName = "peers"
|
||||
|
||||
type PeeringListRequest struct {
|
||||
Request *pbpeering.PeeringListRequest
|
||||
structs.QueryOptions
|
||||
}
|
||||
|
||||
func (r *PeeringListRequest) CacheInfo() cache.RequestInfo {
|
||||
info := cache.RequestInfo{
|
||||
Token: r.Token,
|
||||
Datacenter: "",
|
||||
MinIndex: 0,
|
||||
Timeout: 0,
|
||||
MustRevalidate: false,
|
||||
|
||||
// OPTIMIZE(peering): Cache.notifyPollingQuery polls at this interval. We need to revisit how that polling works.
|
||||
// Using an exponential backoff when the result hasn't changed may be preferable.
|
||||
MaxAge: 1 * time.Second,
|
||||
}
|
||||
|
||||
v, err := hashstructure.Hash([]interface{}{
|
||||
r.Request.Partition,
|
||||
}, nil)
|
||||
if err == nil {
|
||||
// If there is an error, we don't set the key. A blank key forces
|
||||
// no cache for this request so the request is forwarded directly
|
||||
// to the server.
|
||||
info.Key = strconv.FormatUint(v, 10)
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
// Peerings supports fetching the list of peers for a given partition or wildcard-specifier.
|
||||
type Peerings struct {
|
||||
RegisterOptionsNoRefresh
|
||||
Client PeeringLister
|
||||
}
|
||||
|
||||
//go:generate mockery --name PeeringLister --inpackage --filename mock_PeeringLister_test.go
|
||||
type PeeringLister interface {
|
||||
PeeringList(
|
||||
ctx context.Context, in *pbpeering.PeeringListRequest, opts ...grpc.CallOption,
|
||||
) (*pbpeering.PeeringListResponse, error)
|
||||
}
|
||||
|
||||
func (t *Peerings) Fetch(_ cache.FetchOptions, req cache.Request) (cache.FetchResult, error) {
|
||||
var result cache.FetchResult
|
||||
|
||||
// The request should be a PeeringListRequest.
|
||||
// We do not need to make a copy of this request type like in other cache types
|
||||
// because the RequestInfo is synthetic.
|
||||
reqReal, ok := req.(*PeeringListRequest)
|
||||
if !ok {
|
||||
return result, fmt.Errorf(
|
||||
"Internal cache failure: request wrong type: %T", req)
|
||||
}
|
||||
|
||||
// Always allow stale - there's no point in hitting leader if the request is
|
||||
// going to be served from cache and end up arbitrarily stale anyway. This
|
||||
// allows cached service-discover to automatically read scale across all
|
||||
// servers too.
|
||||
reqReal.QueryOptions.SetAllowStale(true)
|
||||
|
||||
ctx, err := external.ContextWithQueryOptions(context.Background(), reqReal.QueryOptions)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Fetch
|
||||
reply, err := t.Client.PeeringList(ctx, reqReal.Request)
|
||||
if err != nil {
|
||||
// Return an empty result if the error is due to peering being disabled.
|
||||
// This allows mesh gateways to receive an update and confirm that the watch is set.
|
||||
if e, ok := status.FromError(err); ok && e.Code() == codes.FailedPrecondition {
|
||||
result.Index = 1
|
||||
result.Value = &pbpeering.PeeringListResponse{}
|
||||
return result, nil
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
result.Value = reply
|
||||
result.Index = reply.Index
|
||||
|
||||
return result, nil
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
package cachetype
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/copystructure"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
grpcstatus "google.golang.org/grpc/status"
|
||||
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/proto/pbpeering"
|
||||
)
|
||||
|
||||
func TestPeerings(t *testing.T) {
|
||||
client := NewMockPeeringLister(t)
|
||||
typ := &Peerings{Client: client}
|
||||
|
||||
resp := &pbpeering.PeeringListResponse{
|
||||
Index: 48,
|
||||
Peerings: []*pbpeering.Peering{
|
||||
{
|
||||
Name: "peer1",
|
||||
ID: "8ac403cf-6834-412f-9dfe-0ac6e69bd89f",
|
||||
PeerServerAddresses: []string{"1.2.3.4"},
|
||||
State: pbpeering.PeeringState_ACTIVE,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Expect the proper call.
|
||||
// This also returns the canned response above.
|
||||
client.On("PeeringList", mock.Anything, mock.Anything).
|
||||
Return(resp, nil)
|
||||
|
||||
// Fetch and assert against the result.
|
||||
result, err := typ.Fetch(cache.FetchOptions{}, &PeeringListRequest{
|
||||
Request: &pbpeering.PeeringListRequest{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, cache.FetchResult{
|
||||
Value: resp,
|
||||
Index: 48,
|
||||
}, result)
|
||||
}
|
||||
|
||||
func TestPeerings_PeeringDisabled(t *testing.T) {
|
||||
client := NewMockPeeringLister(t)
|
||||
typ := &Peerings{Client: client}
|
||||
|
||||
var resp *pbpeering.PeeringListResponse
|
||||
|
||||
// Expect the proper call, but return the peering disabled error
|
||||
client.On("PeeringList", mock.Anything, mock.Anything).
|
||||
Return(resp, grpcstatus.Error(codes.FailedPrecondition, "peering must be enabled to use this endpoint"))
|
||||
|
||||
// Fetch and assert against the result.
|
||||
result, err := typ.Fetch(cache.FetchOptions{}, &PeeringListRequest{
|
||||
Request: &pbpeering.PeeringListRequest{},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, result)
|
||||
require.EqualValues(t, 1, result.Index)
|
||||
require.NotNil(t, result.Value)
|
||||
}
|
||||
|
||||
func TestPeerings_badReqType(t *testing.T) {
|
||||
client := pbpeering.NewPeeringServiceClient(nil)
|
||||
typ := &Peerings{Client: client}
|
||||
|
||||
// Fetch
|
||||
_, err := typ.Fetch(cache.FetchOptions{}, cache.TestRequest(
|
||||
t, cache.RequestInfo{Key: "foo", MinIndex: 64}))
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "wrong type")
|
||||
}
|
||||
|
||||
// This test asserts that we can continuously poll this cache type, given that it doesn't support blocking.
|
||||
func TestPeerings_MultipleUpdates(t *testing.T) {
|
||||
c := cache.New(cache.Options{})
|
||||
|
||||
client := NewMockPeeringLister(t)
|
||||
|
||||
// On each mock client call to PeeringList we will increment the index by 1
|
||||
// to simulate new data arriving.
|
||||
resp := &pbpeering.PeeringListResponse{
|
||||
Index: uint64(0),
|
||||
}
|
||||
|
||||
client.On("PeeringList", mock.Anything, mock.Anything).
|
||||
Return(func(ctx context.Context, in *pbpeering.PeeringListRequest, opts ...grpc.CallOption) *pbpeering.PeeringListResponse {
|
||||
resp.Index++
|
||||
// Avoids triggering the race detection by copying the output
|
||||
copyResp, err := copystructure.Copy(resp)
|
||||
require.NoError(t, err)
|
||||
output := copyResp.(*pbpeering.PeeringListResponse)
|
||||
return output
|
||||
}, nil)
|
||||
|
||||
c.RegisterType(PeeringListName, &Peerings{Client: client})
|
||||
|
||||
ch := make(chan cache.UpdateEvent)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
t.Cleanup(cancel)
|
||||
|
||||
require.NoError(t, c.Notify(ctx, PeeringListName, &PeeringListRequest{
|
||||
Request: &pbpeering.PeeringListRequest{},
|
||||
}, "updates", ch))
|
||||
|
||||
i := uint64(1)
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Fatal("context deadline exceeded")
|
||||
return
|
||||
case update := <-ch:
|
||||
// Expect to receive updates for increasing indexes serially.
|
||||
actual := update.Result.(*pbpeering.PeeringListResponse)
|
||||
require.Equal(t, i, actual.Index)
|
||||
i++
|
||||
|
||||
if i > 3 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,8 +83,7 @@ func (t *TrustBundle) Fetch(_ cache.FetchOptions, req cache.Request) (cache.Fetc
|
|||
reqReal.QueryOptions.SetAllowStale(true)
|
||||
|
||||
// Fetch
|
||||
options := structs.QueryOptions{Token: reqReal.Token}
|
||||
ctx, err := external.ContextWithQueryOptions(context.Background(), options)
|
||||
ctx, err := external.ContextWithQueryOptions(context.Background(), reqReal.QueryOptions)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
|
|
@ -5,10 +5,11 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/proto/pbpeering"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
"github.com/hashicorp/consul/proto/pbpeering"
|
||||
)
|
||||
|
||||
func TestTrustBundle(t *testing.T) {
|
||||
|
@ -93,11 +94,12 @@ func TestTrustBundle_MultipleUpdates(t *testing.T) {
|
|||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Fatal("context deadline exceeded")
|
||||
return
|
||||
case update := <-ch:
|
||||
// Expect to receive updates for increasing indexes serially.
|
||||
resp := update.Result.(*pbpeering.TrustBundleReadResponse)
|
||||
require.Equal(t, i, resp.Index)
|
||||
actual := update.Result.(*pbpeering.TrustBundleReadResponse)
|
||||
require.Equal(t, i, actual.Index)
|
||||
i++
|
||||
|
||||
if i > 3 {
|
||||
|
|
|
@ -87,8 +87,7 @@ func (t *TrustBundles) Fetch(_ cache.FetchOptions, req cache.Request) (cache.Fet
|
|||
reqReal.QueryOptions.SetAllowStale(true)
|
||||
|
||||
// Fetch
|
||||
options := structs.QueryOptions{Token: reqReal.Token}
|
||||
ctx, err := external.ContextWithQueryOptions(context.Background(), options)
|
||||
ctx, err := external.ContextWithQueryOptions(context.Background(), reqReal.QueryOptions)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ func TestTrustBundles_MultipleUpdates(t *testing.T) {
|
|||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
t.Fatal("context deadline exceeded")
|
||||
return
|
||||
case update := <-ch:
|
||||
// Expect to receive updates for increasing indexes serially.
|
||||
|
|
|
@ -43,6 +43,7 @@ type Store interface {
|
|||
ReadResolvedServiceConfigEntries(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, upstreamIDs []structs.ServiceID, proxyMode structs.ProxyMode) (uint64, *configentry.ResolvedServiceConfigSet, error)
|
||||
ServiceDiscoveryChain(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, req discoverychain.CompileRequest) (uint64, *structs.CompiledDiscoveryChain, *configentry.DiscoveryChainSet, error)
|
||||
ServiceDump(ws memdb.WatchSet, kind structs.ServiceKind, useKind bool, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error)
|
||||
PeeringList(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.Peering, error)
|
||||
PeeringTrustBundleRead(ws memdb.WatchSet, q state.Query) (uint64, *pbpeering.PeeringTrustBundle, error)
|
||||
PeeringTrustBundleList(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.PeeringTrustBundle, error)
|
||||
TrustBundleListByService(ws memdb.WatchSet, service, dc string, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.PeeringTrustBundle, error)
|
||||
|
|
|
@ -149,7 +149,9 @@ func (r *staticResolver) SwapAuthorizer(authz acl.Authorizer) {
|
|||
r.authorizer = authz
|
||||
}
|
||||
|
||||
func (r *staticResolver) ResolveTokenAndDefaultMeta(token string, entMeta *acl.EnterpriseMeta, authzContext *acl.AuthorizerContext) (resolver.Result, error) {
|
||||
func (r *staticResolver) ResolveTokenAndDefaultMeta(_ string, entMeta *acl.EnterpriseMeta, authzContext *acl.AuthorizerContext) (resolver.Result, error) {
|
||||
entMeta.FillAuthzContext(authzContext)
|
||||
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
return resolver.Result{Authorizer: r.authorizer}, nil
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
package proxycfgglue
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/go-memdb"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
"github.com/hashicorp/consul/agent/cache"
|
||||
cachetype "github.com/hashicorp/consul/agent/cache-types"
|
||||
"github.com/hashicorp/consul/agent/consul/watch"
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
"github.com/hashicorp/consul/proto/pbpeering"
|
||||
)
|
||||
|
||||
// CachePeeringList satisfies the proxycfg.PeeringList interface by sourcing
|
||||
// data from the agent cache.
|
||||
func CachePeeringList(c *cache.Cache) proxycfg.PeeringList {
|
||||
return &cacheProxyDataSource[*cachetype.PeeringListRequest]{c, cachetype.PeeringListName}
|
||||
}
|
||||
|
||||
// ServerPeeringList satisfies the proxycfg.PeeringList interface by sourcing
|
||||
// data from a blocking query against the server's state store.
|
||||
func ServerPeeringList(deps ServerDataSourceDeps) proxycfg.PeeringList {
|
||||
return &serverPeeringList{deps}
|
||||
}
|
||||
|
||||
type serverPeeringList struct {
|
||||
deps ServerDataSourceDeps
|
||||
}
|
||||
|
||||
func (s *serverPeeringList) Notify(ctx context.Context, req *cachetype.PeeringListRequest, correlationID string, ch chan<- proxycfg.UpdateEvent) error {
|
||||
entMeta := structs.DefaultEnterpriseMetaInPartition(req.Request.Partition)
|
||||
|
||||
return watch.ServerLocalNotify(ctx, correlationID, s.deps.GetStore,
|
||||
func(ws memdb.WatchSet, store Store) (uint64, *pbpeering.PeeringListResponse, error) {
|
||||
var authzCtx acl.AuthorizerContext
|
||||
authz, err := s.deps.ACLResolver.ResolveTokenAndDefaultMeta(req.Token, entMeta, &authzCtx)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
if err := authz.ToAllowAuthorizer().PeeringReadAllowed(&authzCtx); err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
index, peerings, err := store.PeeringList(ws, *entMeta)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return index, &pbpeering.PeeringListResponse{
|
||||
Index: index,
|
||||
Peerings: peerings,
|
||||
}, nil
|
||||
},
|
||||
dispatchBlockingQueryUpdate[*pbpeering.PeeringListResponse](ch),
|
||||
)
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package proxycfgglue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/hashicorp/consul/acl"
|
||||
cachetype "github.com/hashicorp/consul/agent/cache-types"
|
||||
"github.com/hashicorp/consul/agent/consul/state"
|
||||
"github.com/hashicorp/consul/agent/proxycfg"
|
||||
"github.com/hashicorp/consul/proto/pbpeering"
|
||||
"github.com/hashicorp/consul/sdk/testutil"
|
||||
)
|
||||
|
||||
func TestServerPeeringList(t *testing.T) {
|
||||
const (
|
||||
index uint64 = 123
|
||||
)
|
||||
|
||||
store := state.NewStateStore(nil)
|
||||
|
||||
req := pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
Name: "peer-01",
|
||||
ID: "00000000-0000-0000-0000-000000000000",
|
||||
},
|
||||
}
|
||||
|
||||
require.NoError(t, store.PeeringWrite(index, &req))
|
||||
|
||||
dataSource := ServerPeeringList(ServerDataSourceDeps{
|
||||
GetStore: func() Store { return store },
|
||||
ACLResolver: newStaticResolver(acl.ManageAll()),
|
||||
})
|
||||
|
||||
eventCh := make(chan proxycfg.UpdateEvent)
|
||||
err := dataSource.Notify(context.Background(), &cachetype.PeeringListRequest{
|
||||
Request: &pbpeering.PeeringListRequest{},
|
||||
}, "", eventCh)
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.RunStep(t, "initial state", func(t *testing.T) {
|
||||
result := getEventResult[*pbpeering.PeeringListResponse](t, eventCh)
|
||||
require.Len(t, result.Peerings, 1)
|
||||
require.Equal(t, "peer-01", result.Peerings[0].Name)
|
||||
require.Equal(t, index, result.Index)
|
||||
})
|
||||
|
||||
testutil.RunStep(t, "add peering", func(t *testing.T) {
|
||||
req = pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
Name: "peer-02",
|
||||
ID: "00000000-0000-0000-0000-000000000001",
|
||||
},
|
||||
}
|
||||
require.NoError(t, store.PeeringWrite(index+1, &req))
|
||||
|
||||
result := getEventResult[*pbpeering.PeeringListResponse](t, eventCh)
|
||||
require.Len(t, result.Peerings, 2)
|
||||
require.Equal(t, "peer-02", result.Peerings[1].Name)
|
||||
require.Equal(t, index+1, result.Index)
|
||||
})
|
||||
}
|
||||
|
||||
func TestServerPeeringList_ACLEnforcement(t *testing.T) {
|
||||
const (
|
||||
index uint64 = 123
|
||||
)
|
||||
|
||||
store := state.NewStateStore(nil)
|
||||
|
||||
req := pbpeering.PeeringWriteRequest{
|
||||
Peering: &pbpeering.Peering{
|
||||
Name: "peer-01",
|
||||
ID: "00000000-0000-0000-0000-000000000000",
|
||||
},
|
||||
}
|
||||
|
||||
require.NoError(t, store.PeeringWrite(index, &req))
|
||||
|
||||
testutil.RunStep(t, "can read", func(t *testing.T) {
|
||||
authz := policyAuthorizer(t, `
|
||||
peering = "read"`)
|
||||
dataSource := ServerPeeringList(ServerDataSourceDeps{
|
||||
GetStore: func() Store { return store },
|
||||
ACLResolver: newStaticResolver(authz),
|
||||
})
|
||||
|
||||
eventCh := make(chan proxycfg.UpdateEvent)
|
||||
err := dataSource.Notify(context.Background(), &cachetype.PeeringListRequest{
|
||||
Request: &pbpeering.PeeringListRequest{},
|
||||
}, "", eventCh)
|
||||
require.NoError(t, err)
|
||||
|
||||
result := getEventResult[*pbpeering.PeeringListResponse](t, eventCh)
|
||||
require.Len(t, result.Peerings, 1)
|
||||
require.Equal(t, "peer-01", result.Peerings[0].Name)
|
||||
require.Equal(t, index, result.Index)
|
||||
})
|
||||
|
||||
testutil.RunStep(t, "can't read", func(t *testing.T) {
|
||||
authz := policyAuthorizer(t, ``)
|
||||
dataSource := ServerPeeringList(ServerDataSourceDeps{
|
||||
GetStore: func() Store { return store },
|
||||
ACLResolver: newStaticResolver(authz),
|
||||
})
|
||||
|
||||
eventCh := make(chan proxycfg.UpdateEvent)
|
||||
err := dataSource.Notify(context.Background(), &cachetype.PeeringListRequest{
|
||||
Request: &pbpeering.PeeringListRequest{},
|
||||
}, "", eventCh)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = getEventError(t, eventCh)
|
||||
require.Contains(t, err.Error(), "provided token lacks permission 'peering:read'")
|
||||
})
|
||||
}
|
|
@ -103,6 +103,9 @@ type DataSources struct {
|
|||
// notification channel.
|
||||
PeeredUpstreams PeeredUpstreams
|
||||
|
||||
// PeeringList provides peering updates on a notification channel.
|
||||
PeeringList PeeringList
|
||||
|
||||
// PreparedQuery provides updates about the results of a prepared query.
|
||||
PreparedQuery PreparedQuery
|
||||
|
||||
|
@ -215,6 +218,11 @@ type PeeredUpstreams interface {
|
|||
Notify(ctx context.Context, req *structs.PartitionSpecificRequest, correlationID string, ch chan<- UpdateEvent) error
|
||||
}
|
||||
|
||||
// PeeringList is the interface used to consume updates about peerings in the cluster or partition
|
||||
type PeeringList interface {
|
||||
Notify(ctx context.Context, req *cachetype.PeeringListRequest, correlationID string, ch chan<- UpdateEvent) error
|
||||
}
|
||||
|
||||
// PreparedQuery is the interface used to consume updates about the results of
|
||||
// a prepared query.
|
||||
type PreparedQuery interface {
|
||||
|
|
|
@ -3,10 +3,14 @@ package proxycfg
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-hclog"
|
||||
|
||||
cachetype "github.com/hashicorp/consul/agent/cache-types"
|
||||
"github.com/hashicorp/consul/agent/proxycfg/internal/watch"
|
||||
"github.com/hashicorp/consul/agent/structs"
|
||||
|
@ -19,10 +23,18 @@ type handlerMeshGateway struct {
|
|||
handlerState
|
||||
}
|
||||
|
||||
type peerAddressType string
|
||||
|
||||
const (
|
||||
undefinedAddressType peerAddressType = ""
|
||||
ipAddressType peerAddressType = "ip"
|
||||
hostnameAddressType peerAddressType = "hostname"
|
||||
)
|
||||
|
||||
// initialize sets up the watches needed based on the current mesh gateway registration
|
||||
func (s *handlerMeshGateway) initialize(ctx context.Context) (ConfigSnapshot, error) {
|
||||
snap := newConfigSnapshotFromServiceInstance(s.serviceInstance, s.stateConfig)
|
||||
snap.MeshGateway.WatchedConsulServers = watch.NewMap[string, structs.CheckServiceNodes]()
|
||||
snap.MeshGateway.WatchedLocalServers = watch.NewMap[string, structs.CheckServiceNodes]()
|
||||
|
||||
// Watch for root changes
|
||||
err := s.dataSources.CARoots.Notify(ctx, &structs.DCSpecificRequest{
|
||||
|
@ -151,7 +163,7 @@ func (s *handlerMeshGateway) initializeCrossDCWatches(ctx context.Context, snap
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
snap.MeshGateway.WatchedConsulServers.InitWatch(structs.ConsulServiceName, nil)
|
||||
snap.MeshGateway.WatchedLocalServers.InitWatch(structs.ConsulServiceName, nil)
|
||||
}
|
||||
|
||||
err := s.dataSources.Datacenters.Notify(ctx, &structs.DatacentersRequest{
|
||||
|
@ -343,7 +355,7 @@ func (s *handlerMeshGateway) handleUpdate(ctx context.Context, u UpdateEvent, sn
|
|||
}
|
||||
}
|
||||
|
||||
snap.MeshGateway.WatchedConsulServers.Set(structs.ConsulServiceName, resp.Nodes)
|
||||
snap.MeshGateway.WatchedLocalServers.Set(structs.ConsulServiceName, resp.Nodes)
|
||||
|
||||
case exportedServiceListWatchID:
|
||||
exportedServices, ok := u.Result.(*structs.IndexedExportedServiceList)
|
||||
|
@ -515,39 +527,62 @@ func (s *handlerMeshGateway) handleUpdate(ctx context.Context, u UpdateEvent, sn
|
|||
return fmt.Errorf("invalid type for response: %T", u.Result)
|
||||
}
|
||||
|
||||
if resp.Entry == nil {
|
||||
snap.MeshGateway.MeshConfig = nil
|
||||
|
||||
// We avoid managing server watches when WAN federation is enabled since it
|
||||
// always requires server watches.
|
||||
if s.meta[structs.MetaWANFederationKey] != "1" {
|
||||
// If the entry was deleted we cancel watches that may have existed because of
|
||||
// PeerThroughMeshGateways being set in the past.
|
||||
snap.MeshGateway.WatchedConsulServers.CancelWatch(structs.ConsulServiceName)
|
||||
}
|
||||
|
||||
snap.MeshGateway.MeshConfigSet = true
|
||||
return nil
|
||||
}
|
||||
|
||||
meshConf, ok := resp.Entry.(*structs.MeshConfigEntry)
|
||||
if !ok {
|
||||
if resp.Entry != nil && !ok {
|
||||
return fmt.Errorf("invalid type for config entry: %T", resp.Entry)
|
||||
}
|
||||
snap.MeshGateway.MeshConfig = meshConf
|
||||
snap.MeshGateway.MeshConfigSet = true
|
||||
|
||||
// We avoid managing Consul server watches when WAN federation is enabled since it
|
||||
// If we're peering through mesh gateways it means the config entry may be deleted
|
||||
// or the flag was disabled. Here we clean up related watches if they exist.
|
||||
if !meshConf.PeerThroughMeshGateways() {
|
||||
// We avoid canceling server watches when WAN federation is enabled since it
|
||||
// always requires a watch to the local servers.
|
||||
if s.meta[structs.MetaWANFederationKey] != "1" {
|
||||
// If the entry was deleted we cancel watches that may have existed because of
|
||||
// PeerThroughMeshGateways being set in the past.
|
||||
snap.MeshGateway.WatchedLocalServers.CancelWatch(structs.ConsulServiceName)
|
||||
}
|
||||
if snap.MeshGateway.PeerServersWatchCancel != nil {
|
||||
snap.MeshGateway.PeerServersWatchCancel()
|
||||
snap.MeshGateway.PeerServersWatchCancel = nil
|
||||
|
||||
snap.MeshGateway.PeerServers = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// If PeerThroughMeshGateways is enabled, and we are in the default partition,
|
||||
// we need to start watching the list of peering connections in all partitions
|
||||
// to set up outbound routes for the control plane. Consul servers are in the default partition,
|
||||
// so only mesh gateways here have his responsibility.
|
||||
if snap.ProxyID.InDefaultPartition() &&
|
||||
snap.MeshGateway.PeerServersWatchCancel == nil {
|
||||
|
||||
peeringListCtx, cancel := context.WithCancel(ctx)
|
||||
err := s.dataSources.PeeringList.Notify(peeringListCtx, &cachetype.PeeringListRequest{
|
||||
Request: &pbpeering.PeeringListRequest{
|
||||
Partition: structs.WildcardSpecifier,
|
||||
},
|
||||
}, peerServersWatchID, s.ch)
|
||||
if err != nil {
|
||||
meshLogger.Error("failed to register watch for peering list", "error", err)
|
||||
cancel()
|
||||
return err
|
||||
}
|
||||
|
||||
snap.MeshGateway.PeerServersWatchCancel = cancel
|
||||
}
|
||||
|
||||
// We avoid initializing Consul server watches when WAN federation is enabled since it
|
||||
// always requires server watches.
|
||||
if s.meta[structs.MetaWANFederationKey] == "1" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !meshConf.PeerThroughMeshGateways() {
|
||||
snap.MeshGateway.WatchedConsulServers.CancelWatch(structs.ConsulServiceName)
|
||||
return nil
|
||||
}
|
||||
if snap.MeshGateway.WatchedConsulServers.IsWatched(structs.ConsulServiceName) {
|
||||
if snap.MeshGateway.WatchedLocalServers.IsWatched(structs.ConsulServiceName) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -562,7 +597,45 @@ func (s *handlerMeshGateway) handleUpdate(ctx context.Context, u UpdateEvent, sn
|
|||
return fmt.Errorf("failed to watch local consul servers: %w", err)
|
||||
}
|
||||
|
||||
snap.MeshGateway.WatchedConsulServers.InitWatch(structs.ConsulServiceName, cancel)
|
||||
snap.MeshGateway.WatchedLocalServers.InitWatch(structs.ConsulServiceName, cancel)
|
||||
|
||||
case peerServersWatchID:
|
||||
resp, ok := u.Result.(*pbpeering.PeeringListResponse)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid type for response: %T", u.Result)
|
||||
}
|
||||
|
||||
peerServers := make(map[string]PeerServersValue)
|
||||
for _, peering := range resp.Peerings {
|
||||
// We only need to keep track of outbound establish connections
|
||||
// for mesh gateway.
|
||||
if !peering.ShouldDial() || !peering.IsActive() {
|
||||
continue
|
||||
}
|
||||
|
||||
if existing, ok := peerServers[peering.PeerServerName]; ok && existing.Index >= peering.ModifyIndex {
|
||||
// Multiple peerings can reference the same set of Consul servers, since there can be
|
||||
// multiple partitions in a datacenter. Rather than randomly overwriting, we attempt to
|
||||
// use the latest addresses by checking the Raft index associated with the peering.
|
||||
continue
|
||||
}
|
||||
|
||||
hostnames, ips := peerHostnamesAndIPs(meshLogger, peering.Name, peering.PeerServerAddresses)
|
||||
if len(hostnames) > 0 {
|
||||
peerServers[peering.PeerServerName] = PeerServersValue{
|
||||
Addresses: hostnames,
|
||||
Index: peering.ModifyIndex,
|
||||
UseCDS: true,
|
||||
}
|
||||
} else if len(ips) > 0 {
|
||||
peerServers[peering.PeerServerName] = PeerServersValue{
|
||||
Addresses: ips,
|
||||
Index: peering.ModifyIndex,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
snap.MeshGateway.PeerServers = peerServers
|
||||
|
||||
default:
|
||||
switch {
|
||||
|
@ -707,3 +780,40 @@ func (s *handlerMeshGateway) handleUpdate(ctx context.Context, u UpdateEvent, sn
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func peerHostnamesAndIPs(logger hclog.Logger, peerName string, addresses []string) ([]structs.ServiceAddress, []structs.ServiceAddress) {
|
||||
var (
|
||||
hostnames []structs.ServiceAddress
|
||||
ips []structs.ServiceAddress
|
||||
)
|
||||
|
||||
// Sort the input so that the output is also sorted.
|
||||
sort.Strings(addresses)
|
||||
|
||||
for _, addr := range addresses {
|
||||
ip, rawPort, splitErr := net.SplitHostPort(addr)
|
||||
port, convErr := strconv.Atoi(rawPort)
|
||||
|
||||
if splitErr != nil || convErr != nil {
|
||||
logger.Warn("unable to parse ip and port from peer server address. skipping address.",
|
||||
"peer", peerName, "address", addr)
|
||||
}
|
||||
if net.ParseIP(ip) != nil {
|
||||
ips = append(ips, structs.ServiceAddress{
|
||||
Address: ip,
|
||||
Port: port,
|
||||
})
|
||||
} else {
|
||||
hostnames = append(hostnames, structs.ServiceAddress{
|
||||
Address: ip,
|
||||
Port: port,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(hostnames) > 0 && len(ips) > 0 {
|
||||
logger.Warn("peer server address list contains mix of hostnames and IP addresses; only hostnames will be passed to Envoy",
|
||||
"peer", peerName)
|
||||
}
|
||||
return hostnames, ips
|
||||
}
|
||||
|
|
|
@ -348,6 +348,12 @@ func (c *configSnapshotTerminatingGateway) isEmpty() bool {
|
|||
!c.MeshConfigSet
|
||||
}
|
||||
|
||||
type PeerServersValue struct {
|
||||
Addresses []structs.ServiceAddress
|
||||
Index uint64
|
||||
UseCDS bool
|
||||
}
|
||||
|
||||
type PeeringServiceValue struct {
|
||||
Nodes structs.CheckServiceNodes
|
||||
UseCDS bool
|
||||
|
@ -403,11 +409,11 @@ type configSnapshotMeshGateway struct {
|
|||
// datacenter.
|
||||
FedStateGateways map[string]structs.CheckServiceNodes
|
||||
|
||||
// WatchedConsulServers is a map of (structs.ConsulServiceName -> structs.CheckServiceNodes)`
|
||||
// WatchedLocalServers is a map of (structs.ConsulServiceName -> structs.CheckServiceNodes)`
|
||||
// Mesh gateways can spin up watches for local servers both for
|
||||
// WAN federation and for peering. This map ensures we only have one
|
||||
// watch at a time.
|
||||
WatchedConsulServers watch.Map[string, structs.CheckServiceNodes]
|
||||
WatchedLocalServers watch.Map[string, structs.CheckServiceNodes]
|
||||
|
||||
// HostnameDatacenters is a map of datacenters to mesh gateway instances with a hostname as the address.
|
||||
// If hostnames are configured they must be provided to Envoy via CDS not EDS.
|
||||
|
@ -449,6 +455,13 @@ type configSnapshotMeshGateway struct {
|
|||
// leaf cert watch with different parameters.
|
||||
LeafCertWatchCancel context.CancelFunc
|
||||
|
||||
// PeerServers is the map of peering server names to their addresses.
|
||||
PeerServers map[string]PeerServersValue
|
||||
|
||||
// PeerServersWatchCancel is a CancelFunc to use when resetting the watch
|
||||
// on all peerings as it is enabled/disabled.
|
||||
PeerServersWatchCancel context.CancelFunc
|
||||
|
||||
// PeeringTrustBundles is the list of trust bundles for peers where
|
||||
// services have been exported to using this mesh gateway.
|
||||
PeeringTrustBundles []*pbpeering.PeeringTrustBundle
|
||||
|
@ -588,7 +601,7 @@ func (c *configSnapshotMeshGateway) isEmpty() bool {
|
|||
len(c.GatewayGroups) == 0 &&
|
||||
len(c.FedStateGateways) == 0 &&
|
||||
len(c.HostnameDatacenters) == 0 &&
|
||||
c.WatchedConsulServers.Len() == 0 &&
|
||||
c.WatchedLocalServers.Len() == 0 &&
|
||||
c.isEmptyPeering()
|
||||
}
|
||||
|
||||
|
@ -724,7 +737,7 @@ func (s *ConfigSnapshot) Valid() bool {
|
|||
s.TerminatingGateway.MeshConfigSet
|
||||
|
||||
case structs.ServiceKindMeshGateway:
|
||||
if s.MeshGateway.WatchedConsulServers.Len() == 0 {
|
||||
if s.MeshGateway.WatchedLocalServers.Len() == 0 {
|
||||
if s.ServiceMeta[structs.MetaWANFederationKey] == "1" {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ const (
|
|||
serviceResolverIDPrefix = "service-resolver:"
|
||||
serviceIntentionsIDPrefix = "service-intentions:"
|
||||
intentionUpstreamsID = "intention-upstreams"
|
||||
peerServersWatchID = "peer-servers"
|
||||
peeredUpstreamsID = "peered-upstreams"
|
||||
intentionUpstreamsDestinationID = "intention-upstreams-destination"
|
||||
upstreamPeerWatchIDPrefix = "upstream-peer:"
|
||||
|
|
|
@ -133,6 +133,7 @@ func recordWatches(sc *stateConfig) *watchRecorder {
|
|||
IntentionUpstreamsDestination: typedWatchRecorder[*structs.ServiceSpecificRequest]{wr},
|
||||
InternalServiceDump: typedWatchRecorder[*structs.ServiceDumpRequest]{wr},
|
||||
LeafCertificate: typedWatchRecorder[*cachetype.ConnectCALeafRequest]{wr},
|
||||
PeeringList: typedWatchRecorder[*cachetype.PeeringListRequest]{wr},
|
||||
PeeredUpstreams: typedWatchRecorder[*structs.PartitionSpecificRequest]{wr},
|
||||
PreparedQuery: typedWatchRecorder[*structs.PreparedQueryExecuteRequest]{wr},
|
||||
ResolvedServiceConfig: typedWatchRecorder[*structs.ServiceConfigRequest]{wr},
|
||||
|
@ -241,6 +242,14 @@ func genVerifyTrustBundleListWatchForMeshGateway(partition string) verifyWatchRe
|
|||
}
|
||||
}
|
||||
|
||||
func genVerifyPeeringListWatchForMeshGateway() verifyWatchRequest {
|
||||
return func(t testing.TB, request any) {
|
||||
reqReal, ok := request.(*cachetype.PeeringListRequest)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, structs.WildcardSpecifier, reqReal.Request.Partition)
|
||||
}
|
||||
}
|
||||
|
||||
func genVerifyResolverWatch(expectedService, expectedDatacenter, expectedKind string) verifyWatchRequest {
|
||||
return func(t testing.TB, request any) {
|
||||
reqReal, ok := request.(*structs.ConfigEntryQuery)
|
||||
|
@ -1130,6 +1139,7 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
{
|
||||
requiredWatches: map[string]verifyWatchRequest{
|
||||
consulServerListWatchID: genVerifyServiceSpecificPeeredRequest(structs.ConsulServiceName, "", "dc1", "", false),
|
||||
peerServersWatchID: genVerifyPeeringListWatchForMeshGateway(),
|
||||
},
|
||||
events: []UpdateEvent{
|
||||
{
|
||||
|
@ -1166,8 +1176,9 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
},
|
||||
verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) {
|
||||
require.True(t, snap.Valid())
|
||||
require.NotNil(t, snap.MeshGateway.PeerServersWatchCancel)
|
||||
|
||||
servers, ok := snap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
||||
servers, ok := snap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||
require.True(t, ok)
|
||||
|
||||
expect := structs.CheckServiceNodes{
|
||||
|
@ -1198,6 +1209,64 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
require.Equal(t, expect, servers)
|
||||
},
|
||||
},
|
||||
{
|
||||
requiredWatches: map[string]verifyWatchRequest{
|
||||
consulServerListWatchID: genVerifyServiceSpecificPeeredRequest(structs.ConsulServiceName, "", "dc1", "", false),
|
||||
peerServersWatchID: genVerifyPeeringListWatchForMeshGateway(),
|
||||
},
|
||||
events: []UpdateEvent{
|
||||
{
|
||||
CorrelationID: peerServersWatchID,
|
||||
Result: &pbpeering.PeeringListResponse{
|
||||
Peerings: []*pbpeering.Peering{
|
||||
{
|
||||
Name: "peer-bar",
|
||||
PeerServerName: "server.bar.peering.bar-domain",
|
||||
PeerServerAddresses: []string{"1.2.3.4:8443", "2.3.4.5:8443"},
|
||||
ModifyIndex: 30,
|
||||
},
|
||||
{
|
||||
Name: "peer-broken",
|
||||
PeerServerName: "server.broken.peering.broken-domain",
|
||||
PeerServerAddresses: []string{},
|
||||
ModifyIndex: 45,
|
||||
},
|
||||
{
|
||||
Name: "peer-foo-zap",
|
||||
PeerServerName: "server.foo.peering.foo-domain",
|
||||
PeerServerAddresses: []string{"elb.now-aws.com:8443", "1.2.3.4:8443"},
|
||||
ModifyIndex: 20,
|
||||
},
|
||||
{
|
||||
Name: "peer-foo-zip",
|
||||
PeerServerName: "server.foo.peering.foo-domain",
|
||||
PeerServerAddresses: []string{"1.2.3.4:8443", "2.3.4.5:8443"},
|
||||
ModifyIndex: 12,
|
||||
},
|
||||
},
|
||||
},
|
||||
Err: nil,
|
||||
},
|
||||
},
|
||||
verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) {
|
||||
require.True(t, snap.Valid())
|
||||
require.NotNil(t, snap.MeshGateway.PeerServersWatchCancel)
|
||||
|
||||
expect := map[string]PeerServersValue{
|
||||
"server.foo.peering.foo-domain": {
|
||||
Addresses: []structs.ServiceAddress{{Address: "elb.now-aws.com", Port: 8443}},
|
||||
UseCDS: true,
|
||||
Index: 20,
|
||||
},
|
||||
"server.bar.peering.bar-domain": {
|
||||
Addresses: []structs.ServiceAddress{{Address: "1.2.3.4", Port: 8443}, {Address: "2.3.4.5", Port: 8443}},
|
||||
UseCDS: false,
|
||||
Index: 30,
|
||||
},
|
||||
}
|
||||
require.Equal(t, expect, snap.MeshGateway.PeerServers)
|
||||
},
|
||||
},
|
||||
{
|
||||
events: []UpdateEvent{
|
||||
{
|
||||
|
@ -1215,8 +1284,11 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
require.True(t, snap.Valid())
|
||||
require.NotNil(t, snap.MeshConfig())
|
||||
|
||||
require.False(t, snap.MeshGateway.WatchedConsulServers.IsWatched(structs.ConsulServiceName))
|
||||
servers, ok := snap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
||||
require.Nil(t, snap.MeshGateway.PeerServersWatchCancel)
|
||||
require.Empty(t, snap.MeshGateway.PeerServers)
|
||||
|
||||
require.False(t, snap.MeshGateway.WatchedLocalServers.IsWatched(structs.ConsulServiceName))
|
||||
servers, ok := snap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||
require.False(t, ok)
|
||||
require.Empty(t, servers)
|
||||
},
|
||||
|
@ -1234,8 +1306,8 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
|||
require.True(t, snap.Valid())
|
||||
require.Nil(t, snap.MeshConfig())
|
||||
|
||||
require.False(t, snap.MeshGateway.WatchedConsulServers.IsWatched(structs.ConsulServiceName))
|
||||
servers, ok := snap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
||||
require.False(t, snap.MeshGateway.WatchedLocalServers.IsWatched(structs.ConsulServiceName))
|
||||
servers, ok := snap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||
require.False(t, ok)
|
||||
require.Empty(t, servers)
|
||||
},
|
||||
|
|
|
@ -747,6 +747,7 @@ func testConfigSnapshotFixture(
|
|||
IntentionUpstreamsDestination: &noopDataSource[*structs.ServiceSpecificRequest]{},
|
||||
InternalServiceDump: &noopDataSource[*structs.ServiceDumpRequest]{},
|
||||
LeafCertificate: &noopDataSource[*cachetype.ConnectCALeafRequest]{},
|
||||
PeeringList: &noopDataSource[*cachetype.PeeringListRequest]{},
|
||||
PeeredUpstreams: &noopDataSource[*structs.PartitionSpecificRequest]{},
|
||||
PreparedQuery: &noopDataSource[*structs.PreparedQueryExecuteRequest]{},
|
||||
ResolvedServiceConfig: &noopDataSource[*structs.ServiceConfigRequest]{},
|
||||
|
@ -951,6 +952,7 @@ func NewTestDataSources() *TestDataSources {
|
|||
IntentionUpstreamsDestination: NewTestDataSource[*structs.ServiceSpecificRequest, *structs.IndexedServiceList](),
|
||||
InternalServiceDump: NewTestDataSource[*structs.ServiceDumpRequest, *structs.IndexedCheckServiceNodes](),
|
||||
LeafCertificate: NewTestDataSource[*cachetype.ConnectCALeafRequest, *structs.IssuedCert](),
|
||||
PeeringList: NewTestDataSource[*cachetype.PeeringListRequest, *pbpeering.PeeringListResponse](),
|
||||
PreparedQuery: NewTestDataSource[*structs.PreparedQueryExecuteRequest, *structs.PreparedQueryExecuteResponse](),
|
||||
ResolvedServiceConfig: NewTestDataSource[*structs.ServiceConfigRequest, *structs.ServiceConfigResponse](),
|
||||
ServiceList: NewTestDataSource[*structs.DCSpecificRequest, *structs.IndexedServiceList](),
|
||||
|
@ -977,6 +979,7 @@ type TestDataSources struct {
|
|||
IntentionUpstreamsDestination *TestDataSource[*structs.ServiceSpecificRequest, *structs.IndexedServiceList]
|
||||
InternalServiceDump *TestDataSource[*structs.ServiceDumpRequest, *structs.IndexedCheckServiceNodes]
|
||||
LeafCertificate *TestDataSource[*cachetype.ConnectCALeafRequest, *structs.IssuedCert]
|
||||
PeeringList *TestDataSource[*cachetype.PeeringListRequest, *pbpeering.PeeringListResponse]
|
||||
PeeredUpstreams *TestDataSource[*structs.PartitionSpecificRequest, *structs.IndexedPeeredServiceList]
|
||||
PreparedQuery *TestDataSource[*structs.PreparedQueryExecuteRequest, *structs.PreparedQueryExecuteResponse]
|
||||
ResolvedServiceConfig *TestDataSource[*structs.ServiceConfigRequest, *structs.ServiceConfigResponse]
|
||||
|
@ -1003,6 +1006,7 @@ func (t *TestDataSources) ToDataSources() DataSources {
|
|||
IntentionUpstreamsDestination: t.IntentionUpstreamsDestination,
|
||||
InternalServiceDump: t.InternalServiceDump,
|
||||
LeafCertificate: t.LeafCertificate,
|
||||
PeeringList: t.PeeringList,
|
||||
PeeredUpstreams: t.PeeredUpstreams,
|
||||
PreparedQuery: t.PreparedQuery,
|
||||
ResolvedServiceConfig: t.ResolvedServiceConfig,
|
||||
|
|
|
@ -773,6 +773,78 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func(
|
|||
},
|
||||
},
|
||||
)
|
||||
case "peer-through-mesh-gateway":
|
||||
|
||||
extraUpdates = append(extraUpdates,
|
||||
UpdateEvent{
|
||||
CorrelationID: meshConfigEntryID,
|
||||
Result: &structs.ConfigEntryResponse{
|
||||
Entry: &structs.MeshConfigEntry{
|
||||
Peering: &structs.PeeringMeshConfig{
|
||||
PeerThroughMeshGateways: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// We add extra entries that should not necessitate any
|
||||
// xDS changes in Envoy, plus one hostname and one
|
||||
UpdateEvent{
|
||||
CorrelationID: peerServersWatchID,
|
||||
Result: &pbpeering.PeeringListResponse{
|
||||
Peerings: []*pbpeering.Peering{
|
||||
// Not active
|
||||
{
|
||||
Name: "peer-a",
|
||||
PeerServerName: connect.PeeringServerSAN("dc2", "f3f41279-001d-42bb-912e-f6103fb036b8"),
|
||||
PeerServerAddresses: []string{
|
||||
"1.2.3.4:5200",
|
||||
},
|
||||
State: pbpeering.PeeringState_TERMINATED,
|
||||
ModifyIndex: 2,
|
||||
},
|
||||
// No server addresses, so this should only be accepting connections
|
||||
{
|
||||
Name: "peer-b",
|
||||
PeerServerName: connect.PeeringServerSAN("dc2", "0a3f8926-fda9-4274-b6f6-99ee1a43cbda"),
|
||||
PeerServerAddresses: []string{},
|
||||
State: pbpeering.PeeringState_ESTABLISHING,
|
||||
ModifyIndex: 3,
|
||||
},
|
||||
// This should override the peer-c entry since it has a higher index, even though it is processed earlier.
|
||||
{
|
||||
Name: "peer-c-prime",
|
||||
PeerServerName: connect.PeeringServerSAN("dc2", "6d942ff2-6a78-46f4-a52f-915e26c48797"),
|
||||
PeerServerAddresses: []string{
|
||||
"9.10.11.12:5200",
|
||||
"13.14.15.16:5200",
|
||||
},
|
||||
State: pbpeering.PeeringState_ESTABLISHING,
|
||||
ModifyIndex: 20,
|
||||
},
|
||||
// Uses an ip as the address
|
||||
{
|
||||
Name: "peer-c",
|
||||
PeerServerName: connect.PeeringServerSAN("dc2", "6d942ff2-6a78-46f4-a52f-915e26c48797"),
|
||||
PeerServerAddresses: []string{
|
||||
"5.6.7.8:5200",
|
||||
},
|
||||
State: pbpeering.PeeringState_ESTABLISHING,
|
||||
ModifyIndex: 10,
|
||||
},
|
||||
// Uses a hostname as the address
|
||||
{
|
||||
Name: "peer-d",
|
||||
PeerServerName: connect.PeeringServerSAN("dc3", "f622dc37-7238-4485-ab58-0f53864a9ae5"),
|
||||
PeerServerAddresses: []string{
|
||||
"my-load-balancer-1234567890abcdef.elb.us-east-2.amazonaws.com:8080",
|
||||
},
|
||||
State: pbpeering.PeeringState_ESTABLISHING,
|
||||
ModifyIndex: 4,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
default:
|
||||
t.Fatalf("unknown variant: %s", variant)
|
||||
|
|
|
@ -607,7 +607,7 @@ func (s *Server) PeeringList(ctx context.Context, req *pbpeering.PeeringListRequ
|
|||
|
||||
defer metrics.MeasureSince([]string{"peering", "list"}, time.Now())
|
||||
|
||||
_, peerings, err := s.Backend.Store().PeeringList(nil, *entMeta)
|
||||
idx, peerings, err := s.Backend.Store().PeeringList(nil, *entMeta)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -619,7 +619,7 @@ func (s *Server) PeeringList(ctx context.Context, req *pbpeering.PeeringListRequ
|
|||
cPeerings = append(cPeerings, cp)
|
||||
}
|
||||
|
||||
return &pbpeering.PeeringListResponse{Peerings: cPeerings}, nil
|
||||
return &pbpeering.PeeringListResponse{Peerings: cPeerings, Index: idx}, nil
|
||||
}
|
||||
|
||||
// TODO(peering): Get rid of this func when we stop using the stream tracker for imported/ exported services and the peering state
|
||||
|
|
|
@ -818,6 +818,7 @@ func TestPeeringService_List(t *testing.T) {
|
|||
|
||||
expect := &pbpeering.PeeringListResponse{
|
||||
Peerings: []*pbpeering.Peering{bar, foo},
|
||||
Index: 15,
|
||||
}
|
||||
prototest.AssertDeepEqual(t, expect, resp)
|
||||
}
|
||||
|
@ -883,6 +884,7 @@ func TestPeeringService_List_ACLEnforcement(t *testing.T) {
|
|||
token: testTokenPeeringReadSecret,
|
||||
expect: &pbpeering.PeeringListResponse{
|
||||
Peerings: []*pbpeering.Peering{bar, foo},
|
||||
Index: 15,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -345,8 +345,11 @@ func destinationSpecificServiceName(name string, address string) string {
|
|||
func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
keys := cfgSnap.MeshGateway.GatewayKeys()
|
||||
|
||||
// 1 cluster per remote dc/partition + 1 cluster per local service (this is a lower bound - all subset specific clusters will be appended)
|
||||
clusters := make([]proto.Message, 0, len(keys)+len(cfgSnap.MeshGateway.ServiceGroups))
|
||||
// Allocation count (this is a lower bound - all subset specific clusters will be appended):
|
||||
// 1 cluster per remote dc/partition
|
||||
// 1 cluster per local service
|
||||
// 1 cluster per unique peer server (control plane traffic)
|
||||
clusters := make([]proto.Message, 0, len(keys)+len(cfgSnap.MeshGateway.ServiceGroups)+len(cfgSnap.MeshGateway.PeerServers))
|
||||
|
||||
// Generate the remote clusters
|
||||
for _, key := range keys {
|
||||
|
@ -386,7 +389,7 @@ func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.Co
|
|||
}
|
||||
|
||||
// And for the current datacenter, send all flavors appropriately.
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||
for _, srv := range servers {
|
||||
opts := clusterOpts{
|
||||
name: cfgSnap.ServerSNIFn(cfgSnap.Datacenter, srv.Node.Node),
|
||||
|
@ -399,7 +402,7 @@ func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.Co
|
|||
// Create a single cluster for local servers to be dialed by peers.
|
||||
// When peering through gateways we load balance across the local servers. They cannot be addressed individually.
|
||||
if cfg := cfgSnap.MeshConfig(); cfg.PeerThroughMeshGateways() {
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||
|
||||
// Peering control-plane traffic can only ever be handled by the local leader.
|
||||
// We avoid routing to read replicas since they will never be Raft voters.
|
||||
|
@ -432,6 +435,13 @@ func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.Co
|
|||
}
|
||||
clusters = append(clusters, c...)
|
||||
|
||||
// Generate one cluster for each unique peer server for control plane traffic
|
||||
c, err = s.makePeerServerClusters(cfgSnap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clusters = append(clusters, c...)
|
||||
|
||||
return clusters, nil
|
||||
}
|
||||
|
||||
|
@ -445,6 +455,37 @@ func haveVoters(servers structs.CheckServiceNodes) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (s *ResourceGenerator) makePeerServerClusters(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
if cfgSnap.Kind != structs.ServiceKindMeshGateway {
|
||||
return nil, fmt.Errorf("unsupported gateway kind %q", cfgSnap.Kind)
|
||||
}
|
||||
|
||||
clusters := make([]proto.Message, 0, len(cfgSnap.MeshGateway.PeerServers))
|
||||
|
||||
// Peer server names are assumed to already be formatted in SNI notation:
|
||||
// server.<datacenter>.peering.<trust-domain>
|
||||
for name, servers := range cfgSnap.MeshGateway.PeerServers {
|
||||
if len(servers.Addresses) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
var cluster *envoy_cluster_v3.Cluster
|
||||
if servers.UseCDS {
|
||||
cluster = s.makeExternalHostnameCluster(cfgSnap, clusterOpts{
|
||||
name: name,
|
||||
addresses: servers.Addresses,
|
||||
})
|
||||
} else {
|
||||
cluster = s.makeGatewayCluster(cfgSnap, clusterOpts{
|
||||
name: name,
|
||||
})
|
||||
}
|
||||
clusters = append(clusters, cluster)
|
||||
}
|
||||
|
||||
return clusters, nil
|
||||
}
|
||||
|
||||
// clustersFromSnapshotTerminatingGateway returns the xDS API representation of the "clusters"
|
||||
// for a terminating gateway. This will include 1 cluster per Destination associated with this terminating gateway.
|
||||
func (s *ResourceGenerator) clustersFromSnapshotTerminatingGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
|
@ -633,16 +674,20 @@ func (s *ResourceGenerator) makeDestinationClusters(cfgSnap *proxycfg.ConfigSnap
|
|||
|
||||
for _, address := range dest.Addresses {
|
||||
opts := clusterOpts{
|
||||
name: clusterNameForDestination(cfgSnap, svcName.Name, address, svcName.NamespaceOrDefault(), svcName.PartitionOrDefault()),
|
||||
address: address,
|
||||
port: dest.Port,
|
||||
name: clusterNameForDestination(cfgSnap, svcName.Name, address, svcName.NamespaceOrDefault(), svcName.PartitionOrDefault()),
|
||||
addresses: []structs.ServiceAddress{
|
||||
{
|
||||
Address: address,
|
||||
Port: dest.Port,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var cluster *envoy_cluster_v3.Cluster
|
||||
if structs.IsIP(address) {
|
||||
cluster = s.makeTerminatingIPCluster(cfgSnap, opts)
|
||||
cluster = s.makeExternalIPCluster(cfgSnap, opts)
|
||||
} else {
|
||||
cluster = s.makeTerminatingHostnameCluster(cfgSnap, opts)
|
||||
cluster = s.makeExternalHostnameCluster(cfgSnap, opts)
|
||||
}
|
||||
if err := s.injectGatewayDestinationAddons(cfgSnap, cluster, svcName); err != nil {
|
||||
return nil, err
|
||||
|
@ -1438,6 +1483,11 @@ func makeClusterFromUserConfig(configJSON string) (*envoy_cluster_v3.Cluster, er
|
|||
return &c, err
|
||||
}
|
||||
|
||||
type addressPair struct {
|
||||
host string
|
||||
port int
|
||||
}
|
||||
|
||||
type clusterOpts struct {
|
||||
// name for the cluster
|
||||
name string
|
||||
|
@ -1454,9 +1504,9 @@ type clusterOpts struct {
|
|||
// hostnameEndpoints is a list of endpoints with a hostname as their address
|
||||
hostnameEndpoints structs.CheckServiceNodes
|
||||
|
||||
// Corresponds to a valid ip/port in a Destination
|
||||
address string
|
||||
port int
|
||||
// Corresponds to a valid address/port pairs to be routed externally
|
||||
// these addresses will be embedded in the cluster configuration and will never use EDS
|
||||
addresses []structs.ServiceAddress
|
||||
}
|
||||
|
||||
// makeGatewayCluster creates an Envoy cluster for a mesh or terminating gateway
|
||||
|
@ -1584,8 +1634,9 @@ func configureClusterWithHostnames(
|
|||
}
|
||||
}
|
||||
|
||||
// makeTerminatingIPCluster creates an Envoy cluster for a terminating gateway with an ip destination
|
||||
func (s *ResourceGenerator) makeTerminatingIPCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster {
|
||||
// makeExternalIPCluster creates an Envoy cluster for routing to IP addresses outside of Consul
|
||||
// This is used by terminating gateways for Destinations
|
||||
func (s *ResourceGenerator) makeExternalIPCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster {
|
||||
cfg, err := ParseGatewayConfig(snap.Proxy.Config)
|
||||
if err != nil {
|
||||
// Don't hard fail on a config typo, just warn. The parse func returns
|
||||
|
@ -1605,8 +1656,10 @@ func (s *ResourceGenerator) makeTerminatingIPCluster(snap *proxycfg.ConfigSnapsh
|
|||
ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_STATIC},
|
||||
}
|
||||
|
||||
endpoints := []*envoy_endpoint_v3.LbEndpoint{
|
||||
makeEndpoint(opts.address, opts.port),
|
||||
endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, len(opts.addresses))
|
||||
|
||||
for _, pair := range opts.addresses {
|
||||
endpoints = append(endpoints, makeEndpoint(pair.Address, pair.Port))
|
||||
}
|
||||
|
||||
cluster.LoadAssignment = &envoy_endpoint_v3.ClusterLoadAssignment{
|
||||
|
@ -1620,8 +1673,9 @@ func (s *ResourceGenerator) makeTerminatingIPCluster(snap *proxycfg.ConfigSnapsh
|
|||
return cluster
|
||||
}
|
||||
|
||||
// makeTerminatingHostnameCluster creates an Envoy cluster for a terminating gateway with a hostname destination
|
||||
func (s *ResourceGenerator) makeTerminatingHostnameCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster {
|
||||
// makeExternalHostnameCluster creates an Envoy cluster for hostname endpoints that will be resolved with DNS
|
||||
// This is used by both terminating gateways for Destinations, and Mesh Gateways for peering control plane traffice
|
||||
func (s *ResourceGenerator) makeExternalHostnameCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster {
|
||||
cfg, err := ParseGatewayConfig(snap.Proxy.Config)
|
||||
if err != nil {
|
||||
// Don't hard fail on a config typo, just warn. The parse func returns
|
||||
|
@ -1643,16 +1697,20 @@ func (s *ResourceGenerator) makeTerminatingHostnameCluster(snap *proxycfg.Config
|
|||
rate := 10 * time.Second
|
||||
cluster.DnsRefreshRate = durationpb.New(rate)
|
||||
|
||||
address := makeAddress(opts.address, opts.port)
|
||||
endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, len(opts.addresses))
|
||||
|
||||
endpoints := []*envoy_endpoint_v3.LbEndpoint{
|
||||
{
|
||||
for _, pair := range opts.addresses {
|
||||
address := makeAddress(pair.Address, pair.Port)
|
||||
|
||||
endpoint := &envoy_endpoint_v3.LbEndpoint{
|
||||
HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{
|
||||
Endpoint: &envoy_endpoint_v3.Endpoint{
|
||||
Address: address,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
endpoints = append(endpoints, endpoint)
|
||||
}
|
||||
|
||||
cluster.LoadAssignment = &envoy_endpoint_v3.ClusterLoadAssignment{
|
||||
|
|
|
@ -195,7 +195,12 @@ func (s *ResourceGenerator) endpointsFromSnapshotTerminatingGateway(cfgSnap *pro
|
|||
|
||||
func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
keys := cfgSnap.MeshGateway.GatewayKeys()
|
||||
resources := make([]proto.Message, 0, len(keys)+len(cfgSnap.MeshGateway.ServiceGroups))
|
||||
|
||||
// Allocation count (this is a lower bound - all subset specific clusters will be appended):
|
||||
// 1 cluster per remote dc/partition
|
||||
// 1 cluster per local service
|
||||
// 1 cluster per unique peer server (control plane traffic)
|
||||
resources := make([]proto.Message, 0, len(keys)+len(cfgSnap.MeshGateway.ServiceGroups)+len(cfgSnap.MeshGateway.PeerServers))
|
||||
|
||||
for _, key := range keys {
|
||||
if key.Matches(cfgSnap.Datacenter, cfgSnap.ProxyID.PartitionOrDefault()) {
|
||||
|
@ -248,7 +253,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C
|
|||
cfgSnap.ServerSNIFn != nil {
|
||||
var allServersLbEndpoints []*envoy_endpoint_v3.LbEndpoint
|
||||
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||
for _, srv := range servers {
|
||||
clusterName := cfgSnap.ServerSNIFn(cfgSnap.Datacenter, srv.Node.Node)
|
||||
|
||||
|
@ -289,7 +294,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C
|
|||
if cfg := cfgSnap.MeshConfig(); cfg.PeerThroughMeshGateways() {
|
||||
var serverEndpoints []*envoy_endpoint_v3.LbEndpoint
|
||||
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||
for _, srv := range servers {
|
||||
if isReplica := srv.Service.Meta["read_replica"]; isReplica == "true" {
|
||||
// Peering control-plane traffic can only ever be handled by the local leader.
|
||||
|
@ -319,13 +324,14 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C
|
|||
},
|
||||
})
|
||||
}
|
||||
|
||||
resources = append(resources, &envoy_endpoint_v3.ClusterLoadAssignment{
|
||||
ClusterName: connect.PeeringServerSAN(cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain),
|
||||
Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{{
|
||||
LbEndpoints: serverEndpoints,
|
||||
}},
|
||||
})
|
||||
if len(serverEndpoints) > 0 {
|
||||
resources = append(resources, &envoy_endpoint_v3.ClusterLoadAssignment{
|
||||
ClusterName: connect.PeeringServerSAN(cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain),
|
||||
Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{{
|
||||
LbEndpoints: serverEndpoints,
|
||||
}},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the endpoints for each service and its subsets
|
||||
|
@ -349,6 +355,13 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C
|
|||
}
|
||||
resources = append(resources, e...)
|
||||
|
||||
// Generate the endpoints for peer server control planes.
|
||||
e, err = s.makePeerServerEndpointsForMeshGateway(cfgSnap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resources = append(resources, e...)
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
|
@ -440,6 +453,37 @@ func (s *ResourceGenerator) makeEndpointsForOutgoingPeeredServices(
|
|||
return resources, nil
|
||||
}
|
||||
|
||||
func (s *ResourceGenerator) makePeerServerEndpointsForMeshGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
resources := make([]proto.Message, 0, len(cfgSnap.MeshGateway.PeerServers))
|
||||
|
||||
// Peer server names are assumed to already be formatted in SNI notation:
|
||||
// server.<datacenter>.peering.<trust-domain>
|
||||
for name, servers := range cfgSnap.MeshGateway.PeerServers {
|
||||
if servers.UseCDS || len(servers.Addresses) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
es := make([]*envoy_endpoint_v3.LbEndpoint, 0, len(servers.Addresses))
|
||||
|
||||
for _, address := range servers.Addresses {
|
||||
es = append(es, makeEndpoint(address.Address, address.Port))
|
||||
}
|
||||
|
||||
cla := &envoy_endpoint_v3.ClusterLoadAssignment{
|
||||
ClusterName: name,
|
||||
Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{
|
||||
{
|
||||
LbEndpoints: es,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
resources = append(resources, cla)
|
||||
}
|
||||
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func (s *ResourceGenerator) endpointsFromSnapshotIngressGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||
var resources []proto.Message
|
||||
createdClusters := make(map[proxycfg.UpstreamID]bool)
|
||||
|
|
|
@ -1731,6 +1731,10 @@ func (s *ResourceGenerator) makeMeshGatewayListener(name, addr string, port int,
|
|||
})
|
||||
}
|
||||
|
||||
// --------
|
||||
// WAN Federation over mesh gateways
|
||||
// --------
|
||||
|
||||
if cfgSnap.ProxyID.InDefaultPartition() &&
|
||||
cfgSnap.ServiceMeta[structs.MetaWANFederationKey] == "1" &&
|
||||
cfgSnap.ServerSNIFn != nil {
|
||||
|
@ -1757,7 +1761,7 @@ func (s *ResourceGenerator) makeMeshGatewayListener(name, addr string, port int,
|
|||
}
|
||||
|
||||
// Wildcard all flavors to each server.
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||
for _, srv := range servers {
|
||||
clusterName := cfgSnap.ServerSNIFn(cfgSnap.Datacenter, srv.Node.Node)
|
||||
|
||||
|
@ -1778,10 +1782,14 @@ func (s *ResourceGenerator) makeMeshGatewayListener(name, addr string, port int,
|
|||
}
|
||||
}
|
||||
|
||||
// Create a single cluster for local servers to be dialed by peers.
|
||||
// --------
|
||||
// Peering control plane
|
||||
// --------
|
||||
|
||||
// Create a single filter chain for local servers to be dialed by peers.
|
||||
// When peering through gateways we load balance across the local servers. They cannot be addressed individually.
|
||||
if cfg := cfgSnap.MeshConfig(); cfg.PeerThroughMeshGateways() {
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
||||
if cfgSnap.MeshConfig().PeerThroughMeshGateways() {
|
||||
servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||
|
||||
// Peering control-plane traffic can only ever be handled by the local leader.
|
||||
// We avoid routing to read replicas since they will never be Raft voters.
|
||||
|
@ -1805,6 +1813,30 @@ func (s *ResourceGenerator) makeMeshGatewayListener(name, addr string, port int,
|
|||
}
|
||||
}
|
||||
|
||||
// Create a filter chain per outbound peer server cluster. Listen for the SNI provided
|
||||
// as the peer's ServerName.
|
||||
var peerServerFilterChains []*envoy_listener_v3.FilterChain
|
||||
for name := range cfgSnap.MeshGateway.PeerServers {
|
||||
|
||||
dcTCPProxy, err := makeTCPProxyFilter(name, name, "mesh_gateway_remote_peering_servers.")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
peerServerFilterChains = append(peerServerFilterChains, &envoy_listener_v3.FilterChain{
|
||||
FilterChainMatch: makeSNIFilterChainMatch(name),
|
||||
Filters: []*envoy_listener_v3.Filter{
|
||||
dcTCPProxy,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Sort so the output is stable and the listener doesn't get drained
|
||||
sort.Slice(peerServerFilterChains, func(i, j int) bool {
|
||||
return peerServerFilterChains[i].FilterChainMatch.ServerNames[0] < peerServerFilterChains[j].FilterChainMatch.ServerNames[0]
|
||||
})
|
||||
l.FilterChains = append(l.FilterChains, peerServerFilterChains...)
|
||||
|
||||
// This needs to get tacked on at the end as it has no
|
||||
// matching and will act as a catch all
|
||||
l.FilterChains = append(l.FilterChains, sniClusterChain)
|
||||
|
|
|
@ -231,6 +231,12 @@ func getMeshGatewayPeeringGoldenTestCases() []goldenTestCase {
|
|||
return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "imported-services", nil, nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mesh-gateway-with-peer-through-mesh-gateway-enabled",
|
||||
create: func(t testinf.T) *proxycfg.ConfigSnapshot {
|
||||
return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "peer-through-mesh-gateway", nil, nil)
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
54
agent/xds/testdata/clusters/mesh-gateway-with-peer-through-mesh-gateway-enabled.latest.golden
vendored
Normal file
54
agent/xds/testdata/clusters/mesh-gateway-with-peer-through-mesh-gateway-enabled.latest.golden
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "server.dc2.peering.6d942ff2-6a78-46f4-a52f-915e26c48797",
|
||||
"type": "EDS",
|
||||
"edsClusterConfig": {
|
||||
"edsConfig": {
|
||||
"ads": {
|
||||
|
||||
},
|
||||
"resourceApiVersion": "V3"
|
||||
}
|
||||
},
|
||||
"connectTimeout": "5s",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "server.dc3.peering.f622dc37-7238-4485-ab58-0f53864a9ae5",
|
||||
"type": "LOGICAL_DNS",
|
||||
"connectTimeout": "5s",
|
||||
"loadAssignment": {
|
||||
"clusterName": "server.dc3.peering.f622dc37-7238-4485-ab58-0f53864a9ae5",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "my-load-balancer-1234567890abcdef.elb.us-east-2.amazonaws.com",
|
||||
"portValue": 8080
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"dnsRefreshRate": "10s",
|
||||
"dnsLookupFamily": "V4_ONLY",
|
||||
"outlierDetection": {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"nonce": "00000001"
|
||||
}
|
37
agent/xds/testdata/endpoints/mesh-gateway-with-peer-through-mesh-gateway-enabled.latest.golden
vendored
Normal file
37
agent/xds/testdata/endpoints/mesh-gateway-with-peer-through-mesh-gateway-enabled.latest.golden
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment",
|
||||
"clusterName": "server.dc2.peering.6d942ff2-6a78-46f4-a52f-915e26c48797",
|
||||
"endpoints": [
|
||||
{
|
||||
"lbEndpoints": [
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "13.14.15.16",
|
||||
"portValue": 5200
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "9.10.11.12",
|
||||
"portValue": 5200
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment",
|
||||
"nonce": "00000001"
|
||||
}
|
79
agent/xds/testdata/listeners/mesh-gateway-with-peer-through-mesh-gateway-enabled.latest.golden
vendored
Normal file
79
agent/xds/testdata/listeners/mesh-gateway-with-peer-through-mesh-gateway-enabled.latest.golden
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"resources": [
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "default:1.2.3.4:8443",
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "1.2.3.4",
|
||||
"portValue": 8443
|
||||
}
|
||||
},
|
||||
"filterChains": [
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"server.dc2.peering.6d942ff2-6a78-46f4-a52f-915e26c48797"
|
||||
]
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||
"statPrefix": "mesh_gateway_remote_peering_servers.server.dc2.peering.6d942ff2-6a78-46f4-a52f-915e26c48797",
|
||||
"cluster": "server.dc2.peering.6d942ff2-6a78-46f4-a52f-915e26c48797"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"filterChainMatch": {
|
||||
"serverNames": [
|
||||
"server.dc3.peering.f622dc37-7238-4485-ab58-0f53864a9ae5"
|
||||
]
|
||||
},
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||
"statPrefix": "mesh_gateway_remote_peering_servers.server.dc3.peering.f622dc37-7238-4485-ab58-0f53864a9ae5",
|
||||
"cluster": "server.dc3.peering.f622dc37-7238-4485-ab58-0f53864a9ae5"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"filters": [
|
||||
{
|
||||
"name": "envoy.filters.network.sni_cluster",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||
"statPrefix": "mesh_gateway_local.default",
|
||||
"cluster": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"listenerFilters": [
|
||||
{
|
||||
"name": "envoy.filters.listener.tls_inspector",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeUrl": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -17,8 +17,8 @@
|
|||
"name": "envoy.filters.network.tcp_proxy",
|
||||
"typedConfig": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
||||
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul",
|
||||
"statPrefix": "upstream.db-redir.default.default.dc1"
|
||||
"statPrefix": "upstream.db-redir.default.default.dc1",
|
||||
"cluster": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
5
agent/xds/testdata/routes/mesh-gateway-with-peer-through-mesh-gateway-enabled.latest.golden
vendored
Normal file
5
agent/xds/testdata/routes/mesh-gateway-with-peer-through-mesh-gateway-enabled.latest.golden
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"versionInfo": "00000001",
|
||||
"typeUrl": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"nonce": "00000001"
|
||||
}
|
|
@ -792,6 +792,7 @@ type PeeringListResponse struct {
|
|||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Peerings []*Peering `protobuf:"bytes,1,rep,name=Peerings,proto3" json:"Peerings,omitempty"`
|
||||
Index uint64 `protobuf:"varint,2,opt,name=Index,proto3" json:"Index,omitempty"`
|
||||
}
|
||||
|
||||
func (x *PeeringListResponse) Reset() {
|
||||
|
@ -833,6 +834,13 @@ func (x *PeeringListResponse) GetPeerings() []*Peering {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *PeeringListResponse) GetIndex() uint64 {
|
||||
if x != nil {
|
||||
return x.Index
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type PeeringWriteRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
@ -2287,227 +2295,228 @@ var file_proto_pbpeering_peering_proto_rawDesc = []byte{
|
|||
0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x22, 0x5d, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73,
|
||||
0x6f, 0x6e, 0x22, 0x73, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x08, 0x50, 0x65, 0x65,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61,
|
||||
0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e,
|
||||
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x73, 0x22, 0xca, 0x02, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69,
|
||||
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x07, 0x50, 0x65, 0x65,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73,
|
||||
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50,
|
||||
0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12,
|
||||
0x5e, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63,
|
||||
0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x53, 0x65, 0x63, 0x72,
|
||||
0x65, 0x74, 0x73, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52,
|
||||
0x0e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e,
|
||||
0x73, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
|
||||
0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xca, 0x02, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72,
|
||||
0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x44, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x50, 0x65,
|
||||
0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x5e, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e,
|
||||
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
||||
0x04, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x16,
|
||||
0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x48, 0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
|
||||
0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x22, 0x17, 0x0a, 0x15, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74,
|
||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x1f, 0x54, 0x72,
|
||||
0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a,
|
||||
0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a,
|
||||
0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4b,
|
||||
0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x22,
|
||||
0x89, 0x01, 0x0a, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x04, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4f, 0x0a, 0x07, 0x42, 0x75,
|
||||
0x6e, 0x64, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61,
|
||||
0x67, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
|
||||
0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57,
|
||||
0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61,
|
||||
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d,
|
||||
0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x3a, 0x02, 0x38, 0x01, 0x22, 0x16, 0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57,
|
||||
0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x48, 0x0a, 0x14,
|
||||
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74,
|
||||
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72,
|
||||
0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x93, 0x01, 0x0a, 0x1f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||
0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
|
||||
0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x04, 0x4b, 0x69, 0x6e, 0x64, 0x22, 0x89, 0x01, 0x0a, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42,
|
||||
0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e,
|
||||
0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78,
|
||||
0x12, 0x4f, 0x0a, 0x07, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65,
|
||||
0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75,
|
||||
0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x07, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65,
|
||||
0x73, 0x22, 0x4a, 0x0a, 0x16, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65,
|
||||
0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e,
|
||||
0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7e, 0x0a,
|
||||
0x17, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4d,
|
||||
0x0a, 0x06, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35,
|
||||
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
|
||||
0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42,
|
||||
0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x06, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x2d, 0x0a,
|
||||
0x1b, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74,
|
||||
0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02,
|
||||
0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x22, 0x1e, 0x0a, 0x1c,
|
||||
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65,
|
||||
0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x87, 0x01, 0x0a,
|
||||
0x1e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e,
|
||||
0x64, 0x6c, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x65, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42,
|
||||
0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61,
|
||||
0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e,
|
||||
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64,
|
||||
0x6c, 0x65, 0x52, 0x07, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x22, 0x4a, 0x0a, 0x16, 0x54,
|
||||
0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72,
|
||||
0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61,
|
||||
0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7e, 0x0a, 0x17, 0x54, 0x72, 0x75, 0x73, 0x74,
|
||||
0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x04, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4d, 0x0a, 0x06, 0x42, 0x75, 0x6e, 0x64,
|
||||
0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
|
||||
0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52,
|
||||
0x06, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x2d, 0x0a, 0x1b, 0x50, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x22, 0x1e, 0x0a, 0x1c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x87, 0x01, 0x0a, 0x1e, 0x50, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x57, 0x72, 0x69,
|
||||
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x65, 0x0a, 0x12, 0x50, 0x65, 0x65,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
|
||||
0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
|
||||
0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x12, 0x50, 0x65,
|
||||
0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65,
|
||||
0x22, 0x21, 0x0a, 0x1f, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74,
|
||||
0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, 0x1f, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72,
|
||||
0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61,
|
||||
0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50,
|
||||
0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x22, 0x0a, 0x20, 0x50, 0x65, 0x65, 0x72,
|
||||
0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x44, 0x65,
|
||||
0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9a, 0x02, 0x0a,
|
||||
0x14, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d,
|
||||
0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12,
|
||||
0x55, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e,
|
||||
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
||||
0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x38, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65,
|
||||
0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45,
|
||||
0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73,
|
||||
0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3b, 0x0a, 0x15, 0x47, 0x65, 0x6e,
|
||||
0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b,
|
||||
0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xfc, 0x01, 0x0a, 0x10, 0x45, 0x73, 0x74, 0x61, 0x62,
|
||||
0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50,
|
||||
0x6c, 0x65, 0x52, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74,
|
||||
0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x21, 0x0a, 0x1f, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x57, 0x72, 0x69, 0x74,
|
||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, 0x1f, 0x50, 0x65, 0x65,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x44,
|
||||
0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65,
|
||||
0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x22,
|
||||
0x0a, 0x20, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75,
|
||||
0x6e, 0x64, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x9a, 0x02, 0x0a, 0x14, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50,
|
||||
0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50,
|
||||
0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50,
|
||||
0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x50,
|
||||
0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x51, 0x0a, 0x04, 0x4d, 0x65, 0x74,
|
||||
0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63,
|
||||
0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x73, 0x74, 0x61,
|
||||
0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74,
|
||||
0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09,
|
||||
0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
|
||||
0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x13, 0x0a, 0x11, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69,
|
||||
0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x73, 0x0a, 0x0c, 0x50, 0x65,
|
||||
0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e,
|
||||
0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e,
|
||||
0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x53, 0x54, 0x41, 0x42, 0x4c,
|
||||
0x49, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49,
|
||||
0x56, 0x45, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x41, 0x49, 0x4c, 0x49, 0x4e, 0x47, 0x10,
|
||||
0x04, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12,
|
||||
0x0e, 0x0a, 0x0a, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, 0x45, 0x44, 0x10, 0x06, 0x32,
|
||||
0xc0, 0x08, 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
|
||||
0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74,
|
||||
0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e,
|
||||
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a, 0x09, 0x45, 0x73, 0x74, 0x61, 0x62,
|
||||
0x6c, 0x69, 0x73, 0x68, 0x12, 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
|
||||
0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69,
|
||||
0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68,
|
||||
0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x73,
|
||||
0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x7c, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x12, 0x35,
|
||||
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
|
||||
0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
|
||||
0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
|
||||
0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a,
|
||||
0x0b, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x35, 0x2e, 0x68,
|
||||
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
|
||||
0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74,
|
||||
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x55, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
|
||||
0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d,
|
||||
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x37, 0x2e,
|
||||
0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
|
||||
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74,
|
||||
0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x38, 0x0a, 0x17,
|
||||
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x64,
|
||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x53,
|
||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x64, 0x64,
|
||||
0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e,
|
||||
0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
|
||||
0x3b, 0x0a, 0x15, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72,
|
||||
0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
|
||||
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xfc, 0x01, 0x0a,
|
||||
0x10, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a,
|
||||
0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65,
|
||||
0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12,
|
||||
0x51, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e,
|
||||
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
||||
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
|
||||
0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x12, 0x7f, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65,
|
||||
0x12, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74,
|
||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
|
||||
0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65,
|
||||
0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0xa3, 0x01, 0x0a, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c,
|
||||
0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x42,
|
||||
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
|
||||
0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70,
|
||||
0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64,
|
||||
0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73,
|
||||
0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x12, 0x39, 0x2e, 0x68, 0x61,
|
||||
0x67, 0x2e, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65,
|
||||
0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
|
||||
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x13, 0x0a, 0x11, 0x45,
|
||||
0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x2a, 0x73, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65,
|
||||
0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12,
|
||||
0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c,
|
||||
0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0a,
|
||||
0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x41,
|
||||
0x49, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x4c, 0x45, 0x54,
|
||||
0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41,
|
||||
0x54, 0x45, 0x44, 0x10, 0x06, 0x32, 0xc0, 0x08, 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x6e,
|
||||
0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x37, 0x2e, 0x68, 0x61, 0x73,
|
||||
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47,
|
||||
0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
|
||||
0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
|
||||
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a,
|
||||
0x09, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x12, 0x33, 0x2e, 0x68, 0x61, 0x73,
|
||||
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x45,
|
||||
0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73,
|
||||
0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72,
|
||||
0x69, 0x6e, 0x67, 0x2e, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x52, 0x65, 0x61, 0x64, 0x12, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
|
||||
0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x61,
|
||||
0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e,
|
||||
0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
|
||||
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x12, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70,
|
||||
0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68,
|
||||
0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65,
|
||||
0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c,
|
||||
0x65, 0x74, 0x65, 0x12, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
|
||||
0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44,
|
||||
0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68,
|
||||
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7f, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||
0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
|
||||
0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74,
|
||||
0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x42, 0x8a, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
|
||||
0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37,
|
||||
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
|
||||
0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa3, 0x01, 0x0a, 0x18, 0x54, 0x72, 0x75, 0x73,
|
||||
0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x12, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
|
||||
0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75,
|
||||
0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
|
||||
0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x0c, 0x50, 0x65,
|
||||
0x65, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
|
||||
0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
|
||||
0x70, 0x62, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x50,
|
||||
0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e,
|
||||
0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x50, 0x65, 0x65,
|
||||
0x72, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70,
|
||||
0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
|
||||
0x5c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69,
|
||||
0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x47, 0x50, 0x42,
|
||||
0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x48, 0x61, 0x73, 0x68, 0x69,
|
||||
0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75,
|
||||
0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x88, 0x01,
|
||||
0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61,
|
||||
0x64, 0x12, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65,
|
||||
0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c,
|
||||
0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x68,
|
||||
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67,
|
||||
0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x8a, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d,
|
||||
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
|
||||
0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x42, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68,
|
||||
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xa2,
|
||||
0x02, 0x04, 0x48, 0x43, 0x49, 0x50, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
|
||||
0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6c, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73,
|
||||
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xe2, 0x02,
|
||||
0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75,
|
||||
0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x65, 0x65, 0x72, 0x69,
|
||||
0x6e, 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02,
|
||||
0x24, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73,
|
||||
0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x50, 0x65,
|
||||
0x65, 0x72, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
|
|
@ -254,6 +254,7 @@ message PeeringListRequest {
|
|||
|
||||
message PeeringListResponse {
|
||||
repeated Peering Peerings = 1;
|
||||
uint64 Index = 2;
|
||||
}
|
||||
|
||||
message PeeringWriteRequest {
|
||||
|
|
Loading…
Reference in New Issue