mirror of https://github.com/status-im/consul.git
Merge pull request #14917 from hashicorp/dans/NET-718/peering-outbound-mesh-gateway-xds
This commit is contained in:
commit
56d4aba18c
|
@ -4238,6 +4238,7 @@ func (a *Agent) registerCache() {
|
||||||
a.cache.RegisterType(cachetype.CompiledDiscoveryChainName, &cachetype.CompiledDiscoveryChain{RPC: a})
|
a.cache.RegisterType(cachetype.CompiledDiscoveryChainName, &cachetype.CompiledDiscoveryChain{RPC: a})
|
||||||
|
|
||||||
a.cache.RegisterType(cachetype.GatewayServicesName, &cachetype.GatewayServices{RPC: a})
|
a.cache.RegisterType(cachetype.GatewayServicesName, &cachetype.GatewayServices{RPC: a})
|
||||||
|
|
||||||
a.cache.RegisterType(cachetype.ServiceGatewaysName, &cachetype.ServiceGateways{RPC: a})
|
a.cache.RegisterType(cachetype.ServiceGatewaysName, &cachetype.ServiceGateways{RPC: a})
|
||||||
|
|
||||||
a.cache.RegisterType(cachetype.ConfigEntryListName, &cachetype.ConfigEntryList{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.PeeredUpstreamsName, &cachetype.PeeredUpstreams{RPC: a})
|
||||||
|
|
||||||
|
a.cache.RegisterType(cachetype.PeeringListName, &cachetype.Peerings{Client: a.rpcClientPeering})
|
||||||
|
|
||||||
a.registerEntCache()
|
a.registerEntCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4371,6 +4374,7 @@ func (a *Agent) proxyDataSources() proxycfg.DataSources {
|
||||||
InternalServiceDump: proxycfgglue.CacheInternalServiceDump(a.cache),
|
InternalServiceDump: proxycfgglue.CacheInternalServiceDump(a.cache),
|
||||||
LeafCertificate: proxycfgglue.CacheLeafCertificate(a.cache),
|
LeafCertificate: proxycfgglue.CacheLeafCertificate(a.cache),
|
||||||
PeeredUpstreams: proxycfgglue.CachePeeredUpstreams(a.cache),
|
PeeredUpstreams: proxycfgglue.CachePeeredUpstreams(a.cache),
|
||||||
|
PeeringList: proxycfgglue.CachePeeringList(a.cache),
|
||||||
PreparedQuery: proxycfgglue.CachePrepraredQuery(a.cache),
|
PreparedQuery: proxycfgglue.CachePrepraredQuery(a.cache),
|
||||||
ResolvedServiceConfig: proxycfgglue.CacheResolvedServiceConfig(a.cache),
|
ResolvedServiceConfig: proxycfgglue.CacheResolvedServiceConfig(a.cache),
|
||||||
ServiceList: proxycfgglue.CacheServiceList(a.cache),
|
ServiceList: proxycfgglue.CacheServiceList(a.cache),
|
||||||
|
@ -4399,6 +4403,7 @@ func (a *Agent) proxyDataSources() proxycfg.DataSources {
|
||||||
sources.IntentionUpstreams = proxycfgglue.ServerIntentionUpstreams(deps)
|
sources.IntentionUpstreams = proxycfgglue.ServerIntentionUpstreams(deps)
|
||||||
sources.IntentionUpstreamsDestination = proxycfgglue.ServerIntentionUpstreamsDestination(deps)
|
sources.IntentionUpstreamsDestination = proxycfgglue.ServerIntentionUpstreamsDestination(deps)
|
||||||
sources.InternalServiceDump = proxycfgglue.ServerInternalServiceDump(deps, proxycfgglue.CacheInternalServiceDump(a.cache))
|
sources.InternalServiceDump = proxycfgglue.ServerInternalServiceDump(deps, proxycfgglue.CacheInternalServiceDump(a.cache))
|
||||||
|
sources.PeeringList = proxycfgglue.ServerPeeringList(deps)
|
||||||
sources.PeeredUpstreams = proxycfgglue.ServerPeeredUpstreams(deps)
|
sources.PeeredUpstreams = proxycfgglue.ServerPeeredUpstreams(deps)
|
||||||
sources.ResolvedServiceConfig = proxycfgglue.ServerResolvedServiceConfig(deps, proxycfgglue.CacheResolvedServiceConfig(a.cache))
|
sources.ResolvedServiceConfig = proxycfgglue.ServerResolvedServiceConfig(deps, proxycfgglue.CacheResolvedServiceConfig(a.cache))
|
||||||
sources.ServiceList = proxycfgglue.ServerServiceList(deps, proxycfgglue.CacheServiceList(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)
|
reqReal.QueryOptions.SetAllowStale(true)
|
||||||
|
|
||||||
// Fetch
|
// Fetch
|
||||||
options := structs.QueryOptions{Token: reqReal.Token}
|
ctx, err := external.ContextWithQueryOptions(context.Background(), reqReal.QueryOptions)
|
||||||
ctx, err := external.ContextWithQueryOptions(context.Background(), options)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,11 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/agent/cache"
|
|
||||||
"github.com/hashicorp/consul/proto/pbpeering"
|
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/agent/cache"
|
||||||
|
"github.com/hashicorp/consul/proto/pbpeering"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTrustBundle(t *testing.T) {
|
func TestTrustBundle(t *testing.T) {
|
||||||
|
@ -93,11 +94,12 @@ func TestTrustBundle_MultipleUpdates(t *testing.T) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
t.Fatal("context deadline exceeded")
|
||||||
return
|
return
|
||||||
case update := <-ch:
|
case update := <-ch:
|
||||||
// Expect to receive updates for increasing indexes serially.
|
// Expect to receive updates for increasing indexes serially.
|
||||||
resp := update.Result.(*pbpeering.TrustBundleReadResponse)
|
actual := update.Result.(*pbpeering.TrustBundleReadResponse)
|
||||||
require.Equal(t, i, resp.Index)
|
require.Equal(t, i, actual.Index)
|
||||||
i++
|
i++
|
||||||
|
|
||||||
if i > 3 {
|
if i > 3 {
|
||||||
|
|
|
@ -87,8 +87,7 @@ func (t *TrustBundles) Fetch(_ cache.FetchOptions, req cache.Request) (cache.Fet
|
||||||
reqReal.QueryOptions.SetAllowStale(true)
|
reqReal.QueryOptions.SetAllowStale(true)
|
||||||
|
|
||||||
// Fetch
|
// Fetch
|
||||||
options := structs.QueryOptions{Token: reqReal.Token}
|
ctx, err := external.ContextWithQueryOptions(context.Background(), reqReal.QueryOptions)
|
||||||
ctx, err := external.ContextWithQueryOptions(context.Background(), options)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,7 @@ func TestTrustBundles_MultipleUpdates(t *testing.T) {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
t.Fatal("context deadline exceeded")
|
||||||
return
|
return
|
||||||
case update := <-ch:
|
case update := <-ch:
|
||||||
// Expect to receive updates for increasing indexes serially.
|
// 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)
|
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)
|
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)
|
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)
|
PeeringTrustBundleRead(ws memdb.WatchSet, q state.Query) (uint64, *pbpeering.PeeringTrustBundle, error)
|
||||||
PeeringTrustBundleList(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (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)
|
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
|
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()
|
r.mu.Lock()
|
||||||
defer r.mu.Unlock()
|
defer r.mu.Unlock()
|
||||||
return resolver.Result{Authorizer: r.authorizer}, nil
|
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.
|
// notification channel.
|
||||||
PeeredUpstreams PeeredUpstreams
|
PeeredUpstreams PeeredUpstreams
|
||||||
|
|
||||||
|
// PeeringList provides peering updates on a notification channel.
|
||||||
|
PeeringList PeeringList
|
||||||
|
|
||||||
// PreparedQuery provides updates about the results of a prepared query.
|
// PreparedQuery provides updates about the results of a prepared query.
|
||||||
PreparedQuery PreparedQuery
|
PreparedQuery PreparedQuery
|
||||||
|
|
||||||
|
@ -215,6 +218,11 @@ type PeeredUpstreams interface {
|
||||||
Notify(ctx context.Context, req *structs.PartitionSpecificRequest, correlationID string, ch chan<- UpdateEvent) error
|
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
|
// PreparedQuery is the interface used to consume updates about the results of
|
||||||
// a prepared query.
|
// a prepared query.
|
||||||
type PreparedQuery interface {
|
type PreparedQuery interface {
|
||||||
|
|
|
@ -3,10 +3,14 @@ package proxycfg
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-hclog"
|
||||||
|
|
||||||
cachetype "github.com/hashicorp/consul/agent/cache-types"
|
cachetype "github.com/hashicorp/consul/agent/cache-types"
|
||||||
"github.com/hashicorp/consul/agent/proxycfg/internal/watch"
|
"github.com/hashicorp/consul/agent/proxycfg/internal/watch"
|
||||||
"github.com/hashicorp/consul/agent/structs"
|
"github.com/hashicorp/consul/agent/structs"
|
||||||
|
@ -19,10 +23,18 @@ type handlerMeshGateway struct {
|
||||||
handlerState
|
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
|
// initialize sets up the watches needed based on the current mesh gateway registration
|
||||||
func (s *handlerMeshGateway) initialize(ctx context.Context) (ConfigSnapshot, error) {
|
func (s *handlerMeshGateway) initialize(ctx context.Context) (ConfigSnapshot, error) {
|
||||||
snap := newConfigSnapshotFromServiceInstance(s.serviceInstance, s.stateConfig)
|
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
|
// Watch for root changes
|
||||||
err := s.dataSources.CARoots.Notify(ctx, &structs.DCSpecificRequest{
|
err := s.dataSources.CARoots.Notify(ctx, &structs.DCSpecificRequest{
|
||||||
|
@ -151,7 +163,7 @@ func (s *handlerMeshGateway) initializeCrossDCWatches(ctx context.Context, snap
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
snap.MeshGateway.WatchedConsulServers.InitWatch(structs.ConsulServiceName, nil)
|
snap.MeshGateway.WatchedLocalServers.InitWatch(structs.ConsulServiceName, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.dataSources.Datacenters.Notify(ctx, &structs.DatacentersRequest{
|
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:
|
case exportedServiceListWatchID:
|
||||||
exportedServices, ok := u.Result.(*structs.IndexedExportedServiceList)
|
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)
|
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)
|
meshConf, ok := resp.Entry.(*structs.MeshConfigEntry)
|
||||||
if !ok {
|
if resp.Entry != nil && !ok {
|
||||||
return fmt.Errorf("invalid type for config entry: %T", resp.Entry)
|
return fmt.Errorf("invalid type for config entry: %T", resp.Entry)
|
||||||
}
|
}
|
||||||
snap.MeshGateway.MeshConfig = meshConf
|
snap.MeshGateway.MeshConfig = meshConf
|
||||||
snap.MeshGateway.MeshConfigSet = true
|
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.
|
// always requires server watches.
|
||||||
if s.meta[structs.MetaWANFederationKey] == "1" {
|
if s.meta[structs.MetaWANFederationKey] == "1" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !meshConf.PeerThroughMeshGateways() {
|
if snap.MeshGateway.WatchedLocalServers.IsWatched(structs.ConsulServiceName) {
|
||||||
snap.MeshGateway.WatchedConsulServers.CancelWatch(structs.ConsulServiceName)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if snap.MeshGateway.WatchedConsulServers.IsWatched(structs.ConsulServiceName) {
|
|
||||||
return nil
|
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)
|
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:
|
default:
|
||||||
switch {
|
switch {
|
||||||
|
@ -707,3 +780,40 @@ func (s *handlerMeshGateway) handleUpdate(ctx context.Context, u UpdateEvent, sn
|
||||||
|
|
||||||
return nil
|
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
|
!c.MeshConfigSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PeerServersValue struct {
|
||||||
|
Addresses []structs.ServiceAddress
|
||||||
|
Index uint64
|
||||||
|
UseCDS bool
|
||||||
|
}
|
||||||
|
|
||||||
type PeeringServiceValue struct {
|
type PeeringServiceValue struct {
|
||||||
Nodes structs.CheckServiceNodes
|
Nodes structs.CheckServiceNodes
|
||||||
UseCDS bool
|
UseCDS bool
|
||||||
|
@ -403,11 +409,11 @@ type configSnapshotMeshGateway struct {
|
||||||
// datacenter.
|
// datacenter.
|
||||||
FedStateGateways map[string]structs.CheckServiceNodes
|
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
|
// Mesh gateways can spin up watches for local servers both for
|
||||||
// WAN federation and for peering. This map ensures we only have one
|
// WAN federation and for peering. This map ensures we only have one
|
||||||
// watch at a time.
|
// 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.
|
// 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.
|
// 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.
|
// leaf cert watch with different parameters.
|
||||||
LeafCertWatchCancel context.CancelFunc
|
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
|
// PeeringTrustBundles is the list of trust bundles for peers where
|
||||||
// services have been exported to using this mesh gateway.
|
// services have been exported to using this mesh gateway.
|
||||||
PeeringTrustBundles []*pbpeering.PeeringTrustBundle
|
PeeringTrustBundles []*pbpeering.PeeringTrustBundle
|
||||||
|
@ -588,7 +601,7 @@ func (c *configSnapshotMeshGateway) isEmpty() bool {
|
||||||
len(c.GatewayGroups) == 0 &&
|
len(c.GatewayGroups) == 0 &&
|
||||||
len(c.FedStateGateways) == 0 &&
|
len(c.FedStateGateways) == 0 &&
|
||||||
len(c.HostnameDatacenters) == 0 &&
|
len(c.HostnameDatacenters) == 0 &&
|
||||||
c.WatchedConsulServers.Len() == 0 &&
|
c.WatchedLocalServers.Len() == 0 &&
|
||||||
c.isEmptyPeering()
|
c.isEmptyPeering()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,7 +737,7 @@ func (s *ConfigSnapshot) Valid() bool {
|
||||||
s.TerminatingGateway.MeshConfigSet
|
s.TerminatingGateway.MeshConfigSet
|
||||||
|
|
||||||
case structs.ServiceKindMeshGateway:
|
case structs.ServiceKindMeshGateway:
|
||||||
if s.MeshGateway.WatchedConsulServers.Len() == 0 {
|
if s.MeshGateway.WatchedLocalServers.Len() == 0 {
|
||||||
if s.ServiceMeta[structs.MetaWANFederationKey] == "1" {
|
if s.ServiceMeta[structs.MetaWANFederationKey] == "1" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ const (
|
||||||
serviceResolverIDPrefix = "service-resolver:"
|
serviceResolverIDPrefix = "service-resolver:"
|
||||||
serviceIntentionsIDPrefix = "service-intentions:"
|
serviceIntentionsIDPrefix = "service-intentions:"
|
||||||
intentionUpstreamsID = "intention-upstreams"
|
intentionUpstreamsID = "intention-upstreams"
|
||||||
|
peerServersWatchID = "peer-servers"
|
||||||
peeredUpstreamsID = "peered-upstreams"
|
peeredUpstreamsID = "peered-upstreams"
|
||||||
intentionUpstreamsDestinationID = "intention-upstreams-destination"
|
intentionUpstreamsDestinationID = "intention-upstreams-destination"
|
||||||
upstreamPeerWatchIDPrefix = "upstream-peer:"
|
upstreamPeerWatchIDPrefix = "upstream-peer:"
|
||||||
|
|
|
@ -133,6 +133,7 @@ func recordWatches(sc *stateConfig) *watchRecorder {
|
||||||
IntentionUpstreamsDestination: typedWatchRecorder[*structs.ServiceSpecificRequest]{wr},
|
IntentionUpstreamsDestination: typedWatchRecorder[*structs.ServiceSpecificRequest]{wr},
|
||||||
InternalServiceDump: typedWatchRecorder[*structs.ServiceDumpRequest]{wr},
|
InternalServiceDump: typedWatchRecorder[*structs.ServiceDumpRequest]{wr},
|
||||||
LeafCertificate: typedWatchRecorder[*cachetype.ConnectCALeafRequest]{wr},
|
LeafCertificate: typedWatchRecorder[*cachetype.ConnectCALeafRequest]{wr},
|
||||||
|
PeeringList: typedWatchRecorder[*cachetype.PeeringListRequest]{wr},
|
||||||
PeeredUpstreams: typedWatchRecorder[*structs.PartitionSpecificRequest]{wr},
|
PeeredUpstreams: typedWatchRecorder[*structs.PartitionSpecificRequest]{wr},
|
||||||
PreparedQuery: typedWatchRecorder[*structs.PreparedQueryExecuteRequest]{wr},
|
PreparedQuery: typedWatchRecorder[*structs.PreparedQueryExecuteRequest]{wr},
|
||||||
ResolvedServiceConfig: typedWatchRecorder[*structs.ServiceConfigRequest]{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 {
|
func genVerifyResolverWatch(expectedService, expectedDatacenter, expectedKind string) verifyWatchRequest {
|
||||||
return func(t testing.TB, request any) {
|
return func(t testing.TB, request any) {
|
||||||
reqReal, ok := request.(*structs.ConfigEntryQuery)
|
reqReal, ok := request.(*structs.ConfigEntryQuery)
|
||||||
|
@ -1130,6 +1139,7 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
||||||
{
|
{
|
||||||
requiredWatches: map[string]verifyWatchRequest{
|
requiredWatches: map[string]verifyWatchRequest{
|
||||||
consulServerListWatchID: genVerifyServiceSpecificPeeredRequest(structs.ConsulServiceName, "", "dc1", "", false),
|
consulServerListWatchID: genVerifyServiceSpecificPeeredRequest(structs.ConsulServiceName, "", "dc1", "", false),
|
||||||
|
peerServersWatchID: genVerifyPeeringListWatchForMeshGateway(),
|
||||||
},
|
},
|
||||||
events: []UpdateEvent{
|
events: []UpdateEvent{
|
||||||
{
|
{
|
||||||
|
@ -1166,8 +1176,9 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
||||||
},
|
},
|
||||||
verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) {
|
verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) {
|
||||||
require.True(t, snap.Valid())
|
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)
|
require.True(t, ok)
|
||||||
|
|
||||||
expect := structs.CheckServiceNodes{
|
expect := structs.CheckServiceNodes{
|
||||||
|
@ -1198,6 +1209,64 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
||||||
require.Equal(t, expect, servers)
|
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{
|
events: []UpdateEvent{
|
||||||
{
|
{
|
||||||
|
@ -1215,8 +1284,11 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
||||||
require.True(t, snap.Valid())
|
require.True(t, snap.Valid())
|
||||||
require.NotNil(t, snap.MeshConfig())
|
require.NotNil(t, snap.MeshConfig())
|
||||||
|
|
||||||
require.False(t, snap.MeshGateway.WatchedConsulServers.IsWatched(structs.ConsulServiceName))
|
require.Nil(t, snap.MeshGateway.PeerServersWatchCancel)
|
||||||
servers, ok := snap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
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.False(t, ok)
|
||||||
require.Empty(t, servers)
|
require.Empty(t, servers)
|
||||||
},
|
},
|
||||||
|
@ -1234,8 +1306,8 @@ func TestState_WatchesAndUpdates(t *testing.T) {
|
||||||
require.True(t, snap.Valid())
|
require.True(t, snap.Valid())
|
||||||
require.Nil(t, snap.MeshConfig())
|
require.Nil(t, snap.MeshConfig())
|
||||||
|
|
||||||
require.False(t, snap.MeshGateway.WatchedConsulServers.IsWatched(structs.ConsulServiceName))
|
require.False(t, snap.MeshGateway.WatchedLocalServers.IsWatched(structs.ConsulServiceName))
|
||||||
servers, ok := snap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
servers, ok := snap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||||
require.False(t, ok)
|
require.False(t, ok)
|
||||||
require.Empty(t, servers)
|
require.Empty(t, servers)
|
||||||
},
|
},
|
||||||
|
|
|
@ -747,6 +747,7 @@ func testConfigSnapshotFixture(
|
||||||
IntentionUpstreamsDestination: &noopDataSource[*structs.ServiceSpecificRequest]{},
|
IntentionUpstreamsDestination: &noopDataSource[*structs.ServiceSpecificRequest]{},
|
||||||
InternalServiceDump: &noopDataSource[*structs.ServiceDumpRequest]{},
|
InternalServiceDump: &noopDataSource[*structs.ServiceDumpRequest]{},
|
||||||
LeafCertificate: &noopDataSource[*cachetype.ConnectCALeafRequest]{},
|
LeafCertificate: &noopDataSource[*cachetype.ConnectCALeafRequest]{},
|
||||||
|
PeeringList: &noopDataSource[*cachetype.PeeringListRequest]{},
|
||||||
PeeredUpstreams: &noopDataSource[*structs.PartitionSpecificRequest]{},
|
PeeredUpstreams: &noopDataSource[*structs.PartitionSpecificRequest]{},
|
||||||
PreparedQuery: &noopDataSource[*structs.PreparedQueryExecuteRequest]{},
|
PreparedQuery: &noopDataSource[*structs.PreparedQueryExecuteRequest]{},
|
||||||
ResolvedServiceConfig: &noopDataSource[*structs.ServiceConfigRequest]{},
|
ResolvedServiceConfig: &noopDataSource[*structs.ServiceConfigRequest]{},
|
||||||
|
@ -951,6 +952,7 @@ func NewTestDataSources() *TestDataSources {
|
||||||
IntentionUpstreamsDestination: NewTestDataSource[*structs.ServiceSpecificRequest, *structs.IndexedServiceList](),
|
IntentionUpstreamsDestination: NewTestDataSource[*structs.ServiceSpecificRequest, *structs.IndexedServiceList](),
|
||||||
InternalServiceDump: NewTestDataSource[*structs.ServiceDumpRequest, *structs.IndexedCheckServiceNodes](),
|
InternalServiceDump: NewTestDataSource[*structs.ServiceDumpRequest, *structs.IndexedCheckServiceNodes](),
|
||||||
LeafCertificate: NewTestDataSource[*cachetype.ConnectCALeafRequest, *structs.IssuedCert](),
|
LeafCertificate: NewTestDataSource[*cachetype.ConnectCALeafRequest, *structs.IssuedCert](),
|
||||||
|
PeeringList: NewTestDataSource[*cachetype.PeeringListRequest, *pbpeering.PeeringListResponse](),
|
||||||
PreparedQuery: NewTestDataSource[*structs.PreparedQueryExecuteRequest, *structs.PreparedQueryExecuteResponse](),
|
PreparedQuery: NewTestDataSource[*structs.PreparedQueryExecuteRequest, *structs.PreparedQueryExecuteResponse](),
|
||||||
ResolvedServiceConfig: NewTestDataSource[*structs.ServiceConfigRequest, *structs.ServiceConfigResponse](),
|
ResolvedServiceConfig: NewTestDataSource[*structs.ServiceConfigRequest, *structs.ServiceConfigResponse](),
|
||||||
ServiceList: NewTestDataSource[*structs.DCSpecificRequest, *structs.IndexedServiceList](),
|
ServiceList: NewTestDataSource[*structs.DCSpecificRequest, *structs.IndexedServiceList](),
|
||||||
|
@ -977,6 +979,7 @@ type TestDataSources struct {
|
||||||
IntentionUpstreamsDestination *TestDataSource[*structs.ServiceSpecificRequest, *structs.IndexedServiceList]
|
IntentionUpstreamsDestination *TestDataSource[*structs.ServiceSpecificRequest, *structs.IndexedServiceList]
|
||||||
InternalServiceDump *TestDataSource[*structs.ServiceDumpRequest, *structs.IndexedCheckServiceNodes]
|
InternalServiceDump *TestDataSource[*structs.ServiceDumpRequest, *structs.IndexedCheckServiceNodes]
|
||||||
LeafCertificate *TestDataSource[*cachetype.ConnectCALeafRequest, *structs.IssuedCert]
|
LeafCertificate *TestDataSource[*cachetype.ConnectCALeafRequest, *structs.IssuedCert]
|
||||||
|
PeeringList *TestDataSource[*cachetype.PeeringListRequest, *pbpeering.PeeringListResponse]
|
||||||
PeeredUpstreams *TestDataSource[*structs.PartitionSpecificRequest, *structs.IndexedPeeredServiceList]
|
PeeredUpstreams *TestDataSource[*structs.PartitionSpecificRequest, *structs.IndexedPeeredServiceList]
|
||||||
PreparedQuery *TestDataSource[*structs.PreparedQueryExecuteRequest, *structs.PreparedQueryExecuteResponse]
|
PreparedQuery *TestDataSource[*structs.PreparedQueryExecuteRequest, *structs.PreparedQueryExecuteResponse]
|
||||||
ResolvedServiceConfig *TestDataSource[*structs.ServiceConfigRequest, *structs.ServiceConfigResponse]
|
ResolvedServiceConfig *TestDataSource[*structs.ServiceConfigRequest, *structs.ServiceConfigResponse]
|
||||||
|
@ -1003,6 +1006,7 @@ func (t *TestDataSources) ToDataSources() DataSources {
|
||||||
IntentionUpstreamsDestination: t.IntentionUpstreamsDestination,
|
IntentionUpstreamsDestination: t.IntentionUpstreamsDestination,
|
||||||
InternalServiceDump: t.InternalServiceDump,
|
InternalServiceDump: t.InternalServiceDump,
|
||||||
LeafCertificate: t.LeafCertificate,
|
LeafCertificate: t.LeafCertificate,
|
||||||
|
PeeringList: t.PeeringList,
|
||||||
PeeredUpstreams: t.PeeredUpstreams,
|
PeeredUpstreams: t.PeeredUpstreams,
|
||||||
PreparedQuery: t.PreparedQuery,
|
PreparedQuery: t.PreparedQuery,
|
||||||
ResolvedServiceConfig: t.ResolvedServiceConfig,
|
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:
|
default:
|
||||||
t.Fatalf("unknown variant: %s", variant)
|
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())
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -619,7 +619,7 @@ func (s *Server) PeeringList(ctx context.Context, req *pbpeering.PeeringListRequ
|
||||||
cPeerings = append(cPeerings, cp)
|
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
|
// 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{
|
expect := &pbpeering.PeeringListResponse{
|
||||||
Peerings: []*pbpeering.Peering{bar, foo},
|
Peerings: []*pbpeering.Peering{bar, foo},
|
||||||
|
Index: 15,
|
||||||
}
|
}
|
||||||
prototest.AssertDeepEqual(t, expect, resp)
|
prototest.AssertDeepEqual(t, expect, resp)
|
||||||
}
|
}
|
||||||
|
@ -883,6 +884,7 @@ func TestPeeringService_List_ACLEnforcement(t *testing.T) {
|
||||||
token: testTokenPeeringReadSecret,
|
token: testTokenPeeringReadSecret,
|
||||||
expect: &pbpeering.PeeringListResponse{
|
expect: &pbpeering.PeeringListResponse{
|
||||||
Peerings: []*pbpeering.Peering{bar, foo},
|
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) {
|
func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||||
keys := cfgSnap.MeshGateway.GatewayKeys()
|
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)
|
// Allocation count (this is a lower bound - all subset specific clusters will be appended):
|
||||||
clusters := make([]proto.Message, 0, len(keys)+len(cfgSnap.MeshGateway.ServiceGroups))
|
// 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
|
// Generate the remote clusters
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
|
@ -386,7 +389,7 @@ func (s *ResourceGenerator) clustersFromSnapshotMeshGateway(cfgSnap *proxycfg.Co
|
||||||
}
|
}
|
||||||
|
|
||||||
// And for the current datacenter, send all flavors appropriately.
|
// 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 {
|
for _, srv := range servers {
|
||||||
opts := clusterOpts{
|
opts := clusterOpts{
|
||||||
name: cfgSnap.ServerSNIFn(cfgSnap.Datacenter, srv.Node.Node),
|
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.
|
// 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.
|
// When peering through gateways we load balance across the local servers. They cannot be addressed individually.
|
||||||
if cfg := cfgSnap.MeshConfig(); cfg.PeerThroughMeshGateways() {
|
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.
|
// 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.
|
// 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...)
|
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
|
return clusters, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,6 +455,37 @@ func haveVoters(servers structs.CheckServiceNodes) bool {
|
||||||
return false
|
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"
|
// 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.
|
// 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) {
|
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 {
|
for _, address := range dest.Addresses {
|
||||||
opts := clusterOpts{
|
opts := clusterOpts{
|
||||||
name: clusterNameForDestination(cfgSnap, svcName.Name, address, svcName.NamespaceOrDefault(), svcName.PartitionOrDefault()),
|
name: clusterNameForDestination(cfgSnap, svcName.Name, address, svcName.NamespaceOrDefault(), svcName.PartitionOrDefault()),
|
||||||
address: address,
|
addresses: []structs.ServiceAddress{
|
||||||
port: dest.Port,
|
{
|
||||||
|
Address: address,
|
||||||
|
Port: dest.Port,
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var cluster *envoy_cluster_v3.Cluster
|
var cluster *envoy_cluster_v3.Cluster
|
||||||
if structs.IsIP(address) {
|
if structs.IsIP(address) {
|
||||||
cluster = s.makeTerminatingIPCluster(cfgSnap, opts)
|
cluster = s.makeExternalIPCluster(cfgSnap, opts)
|
||||||
} else {
|
} else {
|
||||||
cluster = s.makeTerminatingHostnameCluster(cfgSnap, opts)
|
cluster = s.makeExternalHostnameCluster(cfgSnap, opts)
|
||||||
}
|
}
|
||||||
if err := s.injectGatewayDestinationAddons(cfgSnap, cluster, svcName); err != nil {
|
if err := s.injectGatewayDestinationAddons(cfgSnap, cluster, svcName); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1438,6 +1483,11 @@ func makeClusterFromUserConfig(configJSON string) (*envoy_cluster_v3.Cluster, er
|
||||||
return &c, err
|
return &c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type addressPair struct {
|
||||||
|
host string
|
||||||
|
port int
|
||||||
|
}
|
||||||
|
|
||||||
type clusterOpts struct {
|
type clusterOpts struct {
|
||||||
// name for the cluster
|
// name for the cluster
|
||||||
name string
|
name string
|
||||||
|
@ -1454,9 +1504,9 @@ type clusterOpts struct {
|
||||||
// hostnameEndpoints is a list of endpoints with a hostname as their address
|
// hostnameEndpoints is a list of endpoints with a hostname as their address
|
||||||
hostnameEndpoints structs.CheckServiceNodes
|
hostnameEndpoints structs.CheckServiceNodes
|
||||||
|
|
||||||
// Corresponds to a valid ip/port in a Destination
|
// Corresponds to a valid address/port pairs to be routed externally
|
||||||
address string
|
// these addresses will be embedded in the cluster configuration and will never use EDS
|
||||||
port int
|
addresses []structs.ServiceAddress
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeGatewayCluster creates an Envoy cluster for a mesh or terminating gateway
|
// 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
|
// makeExternalIPCluster creates an Envoy cluster for routing to IP addresses outside of Consul
|
||||||
func (s *ResourceGenerator) makeTerminatingIPCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster {
|
// 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)
|
cfg, err := ParseGatewayConfig(snap.Proxy.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't hard fail on a config typo, just warn. The parse func returns
|
// 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},
|
ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: envoy_cluster_v3.Cluster_STATIC},
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints := []*envoy_endpoint_v3.LbEndpoint{
|
endpoints := make([]*envoy_endpoint_v3.LbEndpoint, 0, len(opts.addresses))
|
||||||
makeEndpoint(opts.address, opts.port),
|
|
||||||
|
for _, pair := range opts.addresses {
|
||||||
|
endpoints = append(endpoints, makeEndpoint(pair.Address, pair.Port))
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster.LoadAssignment = &envoy_endpoint_v3.ClusterLoadAssignment{
|
cluster.LoadAssignment = &envoy_endpoint_v3.ClusterLoadAssignment{
|
||||||
|
@ -1620,8 +1673,9 @@ func (s *ResourceGenerator) makeTerminatingIPCluster(snap *proxycfg.ConfigSnapsh
|
||||||
return cluster
|
return cluster
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeTerminatingHostnameCluster creates an Envoy cluster for a terminating gateway with a hostname destination
|
// makeExternalHostnameCluster creates an Envoy cluster for hostname endpoints that will be resolved with DNS
|
||||||
func (s *ResourceGenerator) makeTerminatingHostnameCluster(snap *proxycfg.ConfigSnapshot, opts clusterOpts) *envoy_cluster_v3.Cluster {
|
// 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)
|
cfg, err := ParseGatewayConfig(snap.Proxy.Config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't hard fail on a config typo, just warn. The parse func returns
|
// 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
|
rate := 10 * time.Second
|
||||||
cluster.DnsRefreshRate = durationpb.New(rate)
|
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{
|
HostIdentifier: &envoy_endpoint_v3.LbEndpoint_Endpoint{
|
||||||
Endpoint: &envoy_endpoint_v3.Endpoint{
|
Endpoint: &envoy_endpoint_v3.Endpoint{
|
||||||
Address: address,
|
Address: address,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
|
|
||||||
|
endpoints = append(endpoints, endpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster.LoadAssignment = &envoy_endpoint_v3.ClusterLoadAssignment{
|
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) {
|
func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||||
keys := cfgSnap.MeshGateway.GatewayKeys()
|
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 {
|
for _, key := range keys {
|
||||||
if key.Matches(cfgSnap.Datacenter, cfgSnap.ProxyID.PartitionOrDefault()) {
|
if key.Matches(cfgSnap.Datacenter, cfgSnap.ProxyID.PartitionOrDefault()) {
|
||||||
|
@ -248,7 +253,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C
|
||||||
cfgSnap.ServerSNIFn != nil {
|
cfgSnap.ServerSNIFn != nil {
|
||||||
var allServersLbEndpoints []*envoy_endpoint_v3.LbEndpoint
|
var allServersLbEndpoints []*envoy_endpoint_v3.LbEndpoint
|
||||||
|
|
||||||
servers, _ := cfgSnap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||||
for _, srv := range servers {
|
for _, srv := range servers {
|
||||||
clusterName := cfgSnap.ServerSNIFn(cfgSnap.Datacenter, srv.Node.Node)
|
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() {
|
if cfg := cfgSnap.MeshConfig(); cfg.PeerThroughMeshGateways() {
|
||||||
var serverEndpoints []*envoy_endpoint_v3.LbEndpoint
|
var serverEndpoints []*envoy_endpoint_v3.LbEndpoint
|
||||||
|
|
||||||
servers, _ := cfgSnap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||||
for _, srv := range servers {
|
for _, srv := range servers {
|
||||||
if isReplica := srv.Service.Meta["read_replica"]; isReplica == "true" {
|
if isReplica := srv.Service.Meta["read_replica"]; isReplica == "true" {
|
||||||
// Peering control-plane traffic can only ever be handled by the local leader.
|
// Peering control-plane traffic can only ever be handled by the local leader.
|
||||||
|
@ -319,13 +324,14 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if len(serverEndpoints) > 0 {
|
||||||
resources = append(resources, &envoy_endpoint_v3.ClusterLoadAssignment{
|
resources = append(resources, &envoy_endpoint_v3.ClusterLoadAssignment{
|
||||||
ClusterName: connect.PeeringServerSAN(cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain),
|
ClusterName: connect.PeeringServerSAN(cfgSnap.Datacenter, cfgSnap.Roots.TrustDomain),
|
||||||
Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{{
|
Endpoints: []*envoy_endpoint_v3.LocalityLbEndpoints{{
|
||||||
LbEndpoints: serverEndpoints,
|
LbEndpoints: serverEndpoints,
|
||||||
}},
|
}},
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate the endpoints for each service and its subsets
|
// Generate the endpoints for each service and its subsets
|
||||||
|
@ -349,6 +355,13 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C
|
||||||
}
|
}
|
||||||
resources = append(resources, e...)
|
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
|
return resources, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,6 +453,37 @@ func (s *ResourceGenerator) makeEndpointsForOutgoingPeeredServices(
|
||||||
return resources, nil
|
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) {
|
func (s *ResourceGenerator) endpointsFromSnapshotIngressGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) {
|
||||||
var resources []proto.Message
|
var resources []proto.Message
|
||||||
createdClusters := make(map[proxycfg.UpstreamID]bool)
|
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() &&
|
if cfgSnap.ProxyID.InDefaultPartition() &&
|
||||||
cfgSnap.ServiceMeta[structs.MetaWANFederationKey] == "1" &&
|
cfgSnap.ServiceMeta[structs.MetaWANFederationKey] == "1" &&
|
||||||
cfgSnap.ServerSNIFn != nil {
|
cfgSnap.ServerSNIFn != nil {
|
||||||
|
@ -1757,7 +1761,7 @@ func (s *ResourceGenerator) makeMeshGatewayListener(name, addr string, port int,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wildcard all flavors to each server.
|
// Wildcard all flavors to each server.
|
||||||
servers, _ := cfgSnap.MeshGateway.WatchedConsulServers.Get(structs.ConsulServiceName)
|
servers, _ := cfgSnap.MeshGateway.WatchedLocalServers.Get(structs.ConsulServiceName)
|
||||||
for _, srv := range servers {
|
for _, srv := range servers {
|
||||||
clusterName := cfgSnap.ServerSNIFn(cfgSnap.Datacenter, srv.Node.Node)
|
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.
|
// When peering through gateways we load balance across the local servers. They cannot be addressed individually.
|
||||||
if cfg := cfgSnap.MeshConfig(); cfg.PeerThroughMeshGateways() {
|
if cfgSnap.MeshConfig().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.
|
// 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.
|
// 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
|
// This needs to get tacked on at the end as it has no
|
||||||
// matching and will act as a catch all
|
// matching and will act as a catch all
|
||||||
l.FilterChains = append(l.FilterChains, sniClusterChain)
|
l.FilterChains = append(l.FilterChains, sniClusterChain)
|
||||||
|
|
|
@ -231,6 +231,12 @@ func getMeshGatewayPeeringGoldenTestCases() []goldenTestCase {
|
||||||
return proxycfg.TestConfigSnapshotPeeredMeshGateway(t, "imported-services", nil, nil)
|
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",
|
"name": "envoy.filters.network.tcp_proxy",
|
||||||
"typedConfig": {
|
"typedConfig": {
|
||||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy",
|
"@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
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Peerings []*Peering `protobuf:"bytes,1,rep,name=Peerings,proto3" json:"Peerings,omitempty"`
|
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() {
|
func (x *PeeringListResponse) Reset() {
|
||||||
|
@ -833,6 +834,13 @@ func (x *PeeringListResponse) GetPeerings() []*Peering {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *PeeringListResponse) GetIndex() uint64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Index
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
type PeeringWriteRequest struct {
|
type PeeringWriteRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
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,
|
0x73, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
|
||||||
0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x07, 0x50, 0x65, 0x65,
|
0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xca, 0x02, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72,
|
||||||
0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73,
|
0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||||
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e,
|
0x44, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50,
|
0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e,
|
||||||
0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12,
|
0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65,
|
||||||
0x5e, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x50, 0x65,
|
||||||
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63,
|
0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x5e, 0x0a, 0x0e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73,
|
||||||
0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e,
|
||||||
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,
|
|
||||||
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
|
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,
|
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,
|
0x67, 0x2e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0e, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x52, 0x65,
|
||||||
0x04, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20,
|
||||||
0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
|
||||||
0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20,
|
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x16,
|
0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57,
|
||||||
0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65,
|
0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61,
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x48, 0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d,
|
||||||
0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
|
0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||||
0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||||
0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18,
|
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
0x3a, 0x02, 0x38, 0x01, 0x22, 0x16, 0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57,
|
||||||
0x22, 0x17, 0x0a, 0x15, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74,
|
0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x48, 0x0a, 0x14,
|
||||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x1f, 0x54, 0x72,
|
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71,
|
||||||
0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53,
|
0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a,
|
0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74,
|
||||||
0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72,
|
||||||
0x28, 0x09, 0x52, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12,
|
0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||||
0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01,
|
0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a,
|
0x93, 0x01, 0x0a, 0x1f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c,
|
||||||
0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75,
|
||||||
0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4b,
|
0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61,
|
||||||
0x69, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x22,
|
0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||||
0x89, 0x01, 0x0a, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c,
|
0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61,
|
||||||
0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70,
|
0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70,
|
||||||
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20,
|
0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x01, 0x28, 0x04, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4f, 0x0a, 0x07, 0x42, 0x75,
|
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f,
|
||||||
0x6e, 0x64, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61,
|
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,
|
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,
|
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,
|
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,
|
0x6c, 0x65, 0x52, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74,
|
||||||
0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65,
|
0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x21, 0x0a, 0x1f, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
|
0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x57, 0x72, 0x69, 0x74,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72,
|
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, 0x1f, 0x50, 0x65, 0x65,
|
||||||
0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61,
|
0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x44,
|
||||||
0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7e, 0x0a, 0x17, 0x54, 0x72, 0x75, 0x73, 0x74,
|
0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04,
|
||||||
0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65,
|
||||||
0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20,
|
||||||
0x04, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4d, 0x0a, 0x06, 0x42, 0x75, 0x6e, 0x64,
|
0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x22,
|
||||||
0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
|
0x0a, 0x20, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75,
|
||||||
0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65,
|
0x6e, 0x64, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65,
|
0x73, 0x65, 0x22, 0x9a, 0x02, 0x0a, 0x14, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54,
|
||||||
0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52,
|
0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50,
|
||||||
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,
|
|
||||||
0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 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,
|
0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69,
|
||||||
0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50,
|
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74,
|
||||||
0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x50,
|
0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x55, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20,
|
||||||
0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
|
||||||
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,
|
|
||||||
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 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,
|
0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
|
||||||
0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d,
|
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74,
|
||||||
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x37, 0x2e,
|
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,
|
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,
|
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,
|
0x67, 0x2e, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
|
0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65,
|
||||||
0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
|
||||||
0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69,
|
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
|
||||||
0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x12, 0x7f, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65,
|
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x13, 0x0a, 0x11, 0x45,
|
||||||
0x12, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e,
|
0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||||
0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65,
|
0x2a, 0x73, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65,
|
||||||
0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74,
|
0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, 0x12,
|
||||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
|
0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c,
|
||||||
0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65,
|
0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0a,
|
||||||
0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65,
|
0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x41,
|
||||||
0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
0x49, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x4c, 0x45, 0x54,
|
||||||
0x65, 0x12, 0xa3, 0x01, 0x0a, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c,
|
0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x41,
|
||||||
0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x42,
|
0x54, 0x45, 0x44, 0x10, 0x06, 0x32, 0xc0, 0x08, 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e,
|
||||||
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
|
0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x6e,
|
||||||
0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69,
|
0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x37, 0x2e, 0x68, 0x61, 0x73,
|
||||||
0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69,
|
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e,
|
||||||
0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47,
|
||||||
0x73, 0x74, 0x1a, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63,
|
0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75,
|
||||||
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70,
|
0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
|
||||||
0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64,
|
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
|
||||||
0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52,
|
0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73,
|
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, 0x0a,
|
||||||
0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x12, 0x39, 0x2e, 0x68, 0x61,
|
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,
|
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,
|
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,
|
0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 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,
|
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,
|
0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69,
|
||||||
0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37,
|
||||||
0x73, 0x65, 0x42, 0x8a, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69,
|
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,
|
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,
|
0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75,
|
||||||
0x65, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69,
|
0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65,
|
||||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
|
0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x88, 0x01,
|
||||||
0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f,
|
0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61,
|
||||||
0x70, 0x62, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x50,
|
0x64, 0x12, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f,
|
||||||
0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e,
|
0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65,
|
||||||
0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x50, 0x65, 0x65,
|
0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c,
|
||||||
0x72, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70,
|
0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x68,
|
||||||
0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
|
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e,
|
||||||
0x5c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69,
|
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67,
|
||||||
0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65,
|
0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64,
|
||||||
0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x47, 0x50, 0x42,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x8a, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d,
|
||||||
0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x48, 0x61, 0x73, 0x68, 0x69,
|
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
|
||||||
0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e,
|
0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69,
|
||||||
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x62,
|
0x6e, 0x67, 0x42, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
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 (
|
var (
|
||||||
|
|
|
@ -254,6 +254,7 @@ message PeeringListRequest {
|
||||||
|
|
||||||
message PeeringListResponse {
|
message PeeringListResponse {
|
||||||
repeated Peering Peerings = 1;
|
repeated Peering Peerings = 1;
|
||||||
|
uint64 Index = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PeeringWriteRequest {
|
message PeeringWriteRequest {
|
||||||
|
|
Loading…
Reference in New Issue