diff --git a/.changelog/13677.txt b/.changelog/13677.txt new file mode 100644 index 0000000000..639cc5eb1c --- /dev/null +++ b/.changelog/13677.txt @@ -0,0 +1,4 @@ +```release-note:feature +cli: A new flag for config delete to delete a config entry in a +valid config file, e.g., config delete -filename intention-allow.hcl +``` diff --git a/.changelog/13686.txt b/.changelog/13686.txt new file mode 100644 index 0000000000..e42ee475c4 --- /dev/null +++ b/.changelog/13686.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +ui: Add new CopyableCode component and use it in certain pre-existing areas +``` diff --git a/.changelog/13687.txt b/.changelog/13687.txt new file mode 100644 index 0000000000..53d7a08e33 --- /dev/null +++ b/.changelog/13687.txt @@ -0,0 +1,3 @@ +```release-note:feature +server: broadcast the public grpc port using lan serf and update the consul service in the catalog with the same data +``` diff --git a/.changelog/13699.txt b/.changelog/13699.txt new file mode 100644 index 0000000000..64cde8d97c --- /dev/null +++ b/.changelog/13699.txt @@ -0,0 +1,3 @@ +```release-note:bug +xds: Fix a bug where terminating gateway upstream clusters weren't configured properly when the service protocol was `http2`. +``` diff --git a/.circleci/config.yml b/.circleci/config.yml index ec5d4388d1..a9c434b46b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,7 +34,7 @@ references: ember: &EMBER_IMAGE docker.mirror.hashicorp.services/circleci/node:14-browsers ubuntu: &UBUNTU_CI_IMAGE ubuntu-2004:202201-02 cache: - yarn: &YARN_CACHE_KEY consul-ui-v8-{{ checksum "ui/yarn.lock" }} + yarn: &YARN_CACHE_KEY consul-ui-v9-{{ checksum "ui/yarn.lock" }} steps: install-gotestsum: &install-gotestsum @@ -241,7 +241,9 @@ jobs: - run: name: Install protobuf command: make proto-tools - + - run: + name: "Protobuf Format" + command: make proto-format - run: command: make --always-make proto - run: | @@ -249,7 +251,7 @@ jobs: echo "Generated code was not updated correctly" exit 1 fi - - run: + - run: name: "Protobuf Lint" command: make proto-lint diff --git a/CHANGELOG.md b/CHANGELOG.md index f9f3c9f38f..d77193026b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,41 @@ +## 1.12.3 (July 13, 2022) + +IMPROVEMENTS: + +* Support Vault namespaces in Connect CA by adding RootPKINamespace and +IntermediatePKINamespace fields to the config. [[GH-12904](https://github.com/hashicorp/consul/issues/12904)] +* connect: Update Envoy support matrix to latest patch releases (1.22.2, 1.21.3, 1.20.4, 1.19.5) [[GH-13431](https://github.com/hashicorp/consul/issues/13431)] +* dns: Added support for specifying admin partition in node lookups. [[GH-13421](https://github.com/hashicorp/consul/issues/13421)] +* telemetry: Added a `consul.server.isLeader` metric to track if a server is a leader or not. [[GH-13304](https://github.com/hashicorp/consul/issues/13304)] + +BUG FIXES: + +* agent: Fixed a bug in HTTP handlers where URLs were being decoded twice [[GH-13256](https://github.com/hashicorp/consul/issues/13256)] +* deps: Update go-grpc/grpc, resolving connection memory leak [[GH-13051](https://github.com/hashicorp/consul/issues/13051)] +* fix a bug that caused an error when creating `grpc` or `http2` ingress gateway listeners with multiple services [[GH-13127](https://github.com/hashicorp/consul/issues/13127)] +* ui: Fix incorrect text on certain page empty states [[GH-13409](https://github.com/hashicorp/consul/issues/13409)] +* xds: Fix a bug that resulted in Lambda services not using the payload-passthrough option as expected. [[GH-13607](https://github.com/hashicorp/consul/issues/13607)] +* xds: Fix a bug where terminating gateway upstream clusters weren't configured properly when the service protocol was `http2`. [[GH-13699](https://github.com/hashicorp/consul/issues/13699)] + +## 1.11.7 (July 13, 2022) + +IMPROVEMENTS: + +* connect: Update supported Envoy versions to 1.20.4, 1.19.5, 1.18.6, 1.17.4 [[GH-13434](https://github.com/hashicorp/consul/issues/13434)] + +BUG FIXES: + +* agent: Fixed a bug in HTTP handlers where URLs were being decoded twice [[GH-13265](https://github.com/hashicorp/consul/issues/13265)] +* fix a bug that caused an error when creating `grpc` or `http2` ingress gateway listeners with multiple services [[GH-13127](https://github.com/hashicorp/consul/issues/13127)] +* xds: Fix a bug where terminating gateway upstream clusters weren't configured properly when the service protocol was `http2`. [[GH-13699](https://github.com/hashicorp/consul/issues/13699)] + +## 1.10.12 (July 13, 2022) + +BUG FIXES: + +* agent: Fixed a bug in HTTP handlers where URLs were being decoded twice [[GH-13264](https://github.com/hashicorp/consul/issues/13264)] +* fix a bug that caused an error when creating `grpc` or `http2` ingress gateway listeners with multiple services [[GH-13127](https://github.com/hashicorp/consul/issues/13127)] + ## 1.13.0-alpha2 (June 21, 2022) IMPROVEMENTS: diff --git a/GNUmakefile b/GNUmakefile index 7fa86d2347..6327ea579b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -376,6 +376,18 @@ proto-format: proto-tools proto-lint: proto-tools @buf lint --config proto/buf.yaml --path proto @buf lint --config proto-public/buf.yaml --path proto-public + @for fn in $$(find proto -name '*.proto'); do \ + if [[ "$$fn" = "proto/pbsubscribe/subscribe.proto" ]]; then \ + continue ; \ + elif [[ "$$fn" = "proto/pbpartition/partition.proto" ]]; then \ + continue ; \ + fi ; \ + pkg=$$(grep "^package " "$$fn" | sed 's/^package \(.*\);/\1/'); \ + if [[ "$$pkg" != hashicorp.consul.internal.* ]]; then \ + echo "ERROR: $$fn: is missing 'hashicorp.consul.internal' package prefix: $$pkg" >&2; \ + exit 1; \ + fi \ + done # utility to echo a makefile variable (i.e. 'make print-PROTOC_VERSION') print-% : ; @echo $($*) diff --git a/agent/agent.go b/agent/agent.go index ba1d566417..765c1ab918 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -38,7 +38,7 @@ import ( "github.com/hashicorp/consul/agent/config" "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/consul/agent/dns" - publicgrpc "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/local" "github.com/hashicorp/consul/agent/proxycfg" proxycfgglue "github.com/hashicorp/consul/agent/proxycfg-glue" @@ -213,9 +213,9 @@ type Agent struct { // depending on the configuration delegate delegate - // publicGRPCServer is the gRPC server exposed on the dedicated gRPC port (as + // externalGRPCServer is the gRPC server exposed on the dedicated gRPC port (as // opposed to the multiplexed "server" port). - publicGRPCServer *grpc.Server + externalGRPCServer *grpc.Server // state stores a local representation of the node, // services and checks. Used for anti-entropy. @@ -539,7 +539,7 @@ func (a *Agent) Start(ctx context.Context) error { // This needs to happen after the initial auto-config is loaded, because TLS // can only be configured on the gRPC server at the point of creation. - a.buildPublicGRPCServer() + a.buildExternalGRPCServer() if err := a.startLicenseManager(ctx); err != nil { return err @@ -578,7 +578,7 @@ func (a *Agent) Start(ctx context.Context) error { // Setup either the client or the server. if c.ServerMode { - server, err := consul.NewServer(consulCfg, a.baseDeps.Deps, a.publicGRPCServer) + server, err := consul.NewServer(consulCfg, a.baseDeps.Deps, a.externalGRPCServer) if err != nil { return fmt.Errorf("Failed to start Consul server: %v", err) } @@ -760,13 +760,13 @@ func (a *Agent) Failed() <-chan struct{} { return a.apiServers.failed } -func (a *Agent) buildPublicGRPCServer() { +func (a *Agent) buildExternalGRPCServer() { // TLS is only enabled on the gRPC server if there's an HTTPS port configured. var tls *tlsutil.Configurator if a.config.HTTPSPort > 0 { tls = a.tlsConfigurator } - a.publicGRPCServer = publicgrpc.NewServer(a.logger.Named("grpc.public"), tls) + a.externalGRPCServer = external.NewServer(a.logger.Named("grpc.external"), tls) } func (a *Agent) listenAndServeGRPC() error { @@ -803,7 +803,7 @@ func (a *Agent) listenAndServeGRPC() error { }, a, ) - a.xdsServer.Register(a.publicGRPCServer) + a.xdsServer.Register(a.externalGRPCServer) ln, err := a.startListeners(a.config.GRPCAddrs) if err != nil { @@ -816,7 +816,7 @@ func (a *Agent) listenAndServeGRPC() error { "address", innerL.Addr().String(), "network", innerL.Addr().Network(), ) - err := a.publicGRPCServer.Serve(innerL) + err := a.externalGRPCServer.Serve(innerL) if err != nil { a.logger.Error("gRPC server failed", "error", err) } @@ -1193,6 +1193,8 @@ func newConsulConfig(runtimeCfg *config.RuntimeConfig, logger hclog.Logger) (*co cfg.RPCAddr = runtimeCfg.RPCBindAddr cfg.RPCAdvertise = runtimeCfg.RPCAdvertiseAddr + cfg.GRPCPort = runtimeCfg.GRPCPort + cfg.Segment = runtimeCfg.SegmentName if len(runtimeCfg.Segments) > 0 { segments, err := segmentConfig(runtimeCfg) @@ -1492,7 +1494,7 @@ func (a *Agent) ShutdownAgent() error { } // Stop gRPC - a.publicGRPCServer.Stop() + a.externalGRPCServer.Stop() // Stop the proxy config manager if a.proxyConfig != nil { @@ -4111,6 +4113,8 @@ func (a *Agent) registerCache() { a.cache.RegisterType(cachetype.TrustBundleListName, &cachetype.TrustBundles{Client: a.rpcClientPeering}) + a.cache.RegisterType(cachetype.PeeredUpstreamsName, &cachetype.PeeredUpstreams{RPC: a}) + a.registerEntCache() } diff --git a/agent/consul/client_test.go b/agent/consul/client_test.go index e4dd39fb78..84135ee184 100644 --- a/agent/consul/client_test.go +++ b/agent/consul/client_test.go @@ -18,8 +18,8 @@ import ( msgpackrpc "github.com/hashicorp/consul-net-rpc/net-rpc-msgpackrpc" "github.com/hashicorp/consul/agent/consul/stream" - grpc "github.com/hashicorp/consul/agent/grpc/private" - "github.com/hashicorp/consul/agent/grpc/private/resolver" + grpc "github.com/hashicorp/consul/agent/grpc-internal" + "github.com/hashicorp/consul/agent/grpc-internal/resolver" "github.com/hashicorp/consul/agent/pool" "github.com/hashicorp/consul/agent/router" "github.com/hashicorp/consul/agent/rpc/middleware" diff --git a/agent/consul/config.go b/agent/consul/config.go index 40d627bede..50235c6814 100644 --- a/agent/consul/config.go +++ b/agent/consul/config.go @@ -130,6 +130,9 @@ type Config struct { // RPCSrcAddr is the source address for outgoing RPC connections. RPCSrcAddr *net.TCPAddr + // GRPCPort is the port the public gRPC server listens on. + GRPCPort int + // (Enterprise-only) The network segment this agent is part of. Segment string diff --git a/agent/consul/grpc_integration_test.go b/agent/consul/grpc_integration_test.go index a963832851..c94156f96d 100644 --- a/agent/consul/grpc_integration_test.go +++ b/agent/consul/grpc_integration_test.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/authmethod/testauth" - "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/structs" tokenStore "github.com/hashicorp/consul/agent/token" "github.com/hashicorp/consul/proto-public/pbacl" @@ -26,7 +26,7 @@ func TestGRPCIntegration_ConnectCA_Sign(t *testing.T) { // correctly wiring everything up in the server by: // // * Starting a cluster with multiple servers. - // * Making a request to a follower's public gRPC port. + // * Making a request to a follower's external gRPC port. // * Ensuring that the request is correctly forwarded to the leader. // * Ensuring we get a valid certificate back (so it went through the CAManager). server1, conn1, _ := testGRPCIntegrationServer(t, func(c *Config) { @@ -59,7 +59,7 @@ func TestGRPCIntegration_ConnectCA_Sign(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) t.Cleanup(cancel) - ctx = public.ContextWithToken(ctx, TestDefaultInitialManagementToken) + ctx = external.ContextWithToken(ctx, TestDefaultInitialManagementToken) // This would fail if it wasn't forwarded to the leader. rsp, err := client.Sign(ctx, &pbconnectca.SignRequest{ @@ -96,7 +96,7 @@ func TestGRPCIntegration_ServerDiscovery_WatchServers(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) t.Cleanup(cancel) - ctx = public.ContextWithToken(ctx, TestDefaultInitialManagementToken) + ctx = external.ContextWithToken(ctx, TestDefaultInitialManagementToken) serverStream, err := client.WatchServers(ctx, &pbserverdiscovery.WatchServersRequest{Wan: false}) require.NoError(t, err) diff --git a/agent/consul/leader.go b/agent/consul/leader.go index 85aca70ac3..eb197deb3e 100644 --- a/agent/consul/leader.go +++ b/agent/consul/leader.go @@ -1069,6 +1069,11 @@ func (s *Server) handleAliveMember(member serf.Member, nodeEntMeta *acl.Enterpri }, } + grpcPortStr := member.Tags["grpc_port"] + if v, err := strconv.Atoi(grpcPortStr); err == nil && v > 0 { + service.Meta["grpc_port"] = grpcPortStr + } + // Attempt to join the consul server if err := s.joinConsulServer(member, parts); err != nil { return err diff --git a/agent/consul/leader_peering.go b/agent/consul/leader_peering.go index f698e48ec8..49369bbf74 100644 --- a/agent/consul/leader_peering.go +++ b/agent/consul/leader_peering.go @@ -6,7 +6,6 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "net" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" @@ -18,12 +17,12 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/state" - "github.com/hashicorp/consul/agent/pool" - "github.com/hashicorp/consul/agent/rpc/peering" + "github.com/hashicorp/consul/agent/grpc-external/services/peerstream" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/logging" "github.com/hashicorp/consul/proto/pbpeering" + "github.com/hashicorp/consul/proto/pbpeerstream" ) func (s *Server) startPeeringStreamSync(ctx context.Context) { @@ -86,7 +85,7 @@ func (s *Server) syncPeeringsAndBlock(ctx context.Context, logger hclog.Logger, // 3. accept new stream for [D] // 4. list peerings [A,B,C,D] // 5. terminate [] - connectedStreams := s.peeringService.ConnectedStreams() + connectedStreams := s.peerStreamServer.ConnectedStreams() state := s.fsm.State() @@ -132,7 +131,7 @@ func (s *Server) syncPeeringsAndBlock(ctx context.Context, logger hclog.Logger, continue } - status, found := s.peeringService.StreamStatus(peer.ID) + status, found := s.peerStreamServer.StreamStatus(peer.ID) // TODO(peering): If there is new peering data and a connected stream, should we tear down the stream? // If the data in the updated token is bad, the user wouldn't know until the old servers/certs become invalid. @@ -161,7 +160,7 @@ func (s *Server) syncPeeringsAndBlock(ctx context.Context, logger hclog.Logger, } } - logger.Trace("checking connected streams", "streams", s.peeringService.ConnectedStreams(), "sequence_id", seq) + logger.Trace("checking connected streams", "streams", s.peerStreamServer.ConnectedStreams(), "sequence_id", seq) // Clean up active streams of peerings that were deleted from the state store. // TODO(peering): This is going to trigger shutting down peerings we generated a token for. Is that OK? @@ -239,7 +238,6 @@ func (s *Server) establishStream(ctx context.Context, logger hclog.Logger, peer logger.Trace("dialing peer", "addr", addr) conn, err := grpc.DialContext(retryCtx, addr, - grpc.WithContextDialer(newPeerDialer(addr)), grpc.WithBlock(), tlsOption, ) @@ -248,24 +246,28 @@ func (s *Server) establishStream(ctx context.Context, logger hclog.Logger, peer } defer conn.Close() - client := pbpeering.NewPeeringServiceClient(conn) + client := pbpeerstream.NewPeerStreamServiceClient(conn) stream, err := client.StreamResources(retryCtx) if err != nil { return err } - streamReq := peering.HandleStreamRequest{ + if peer.PeerID == "" { + return fmt.Errorf("expected PeerID to be non empty; the wrong end of peering is being dialed") + } + + streamReq := peerstream.HandleStreamRequest{ LocalID: peer.ID, RemoteID: peer.PeerID, PeerName: peer.Name, Partition: peer.Partition, Stream: stream, } - err = s.peeringService.HandleStream(streamReq) + err = s.peerStreamServer.HandleStream(streamReq) // A nil error indicates that the peering was deleted and the stream needs to be gracefully shutdown. if err == nil { stream.CloseSend() - s.peeringService.DrainStream(streamReq) + s.peerStreamServer.DrainStream(streamReq) // This will cancel the retry-er context, letting us break out of this loop when we want to shut down the stream. cancel() @@ -283,26 +285,6 @@ func (s *Server) establishStream(ctx context.Context, logger hclog.Logger, peer return nil } -func newPeerDialer(peerAddr string) func(context.Context, string) (net.Conn, error) { - return func(ctx context.Context, addr string) (net.Conn, error) { - d := net.Dialer{} - conn, err := d.DialContext(ctx, "tcp", peerAddr) - if err != nil { - return nil, err - } - - // TODO(peering): This is going to need to be revisited. This type uses the TLS settings configured on the agent, but - // for peering we never want mutual TLS because the client peer doesn't share its CA cert. - _, err = conn.Write([]byte{byte(pool.RPCGRPC)}) - if err != nil { - conn.Close() - return nil, err - } - - return conn, nil - } -} - func (s *Server) startPeeringDeferredDeletion(ctx context.Context) { s.leaderRoutineManager.Start(ctx, peeringDeletionRoutineName, s.runPeeringDeletions) } diff --git a/agent/consul/leader_peering_test.go b/agent/consul/leader_peering_test.go index 169ca833f3..222b59279a 100644 --- a/agent/consul/leader_peering_test.go +++ b/agent/consul/leader_peering_test.go @@ -59,7 +59,7 @@ func TestLeader_PeeringSync_Lifecycle_ClientDeletion(t *testing.T) { // S1 should not have a stream tracked for dc2 because s1 generated a token for baz, and therefore needs to wait to be dialed. time.Sleep(1 * time.Second) - _, found := s1.peeringService.StreamStatus(token.PeerID) + _, found := s1.peerStreamServer.StreamStatus(token.PeerID) require.False(t, found) var ( @@ -90,7 +90,7 @@ func TestLeader_PeeringSync_Lifecycle_ClientDeletion(t *testing.T) { require.NoError(t, s2.fsm.State().PeeringWrite(1000, p)) retry.Run(t, func(r *retry.R) { - status, found := s2.peeringService.StreamStatus(p.ID) + status, found := s2.peerStreamServer.StreamStatus(p.ID) require.True(r, found) require.True(r, status.Connected) }) @@ -105,7 +105,7 @@ func TestLeader_PeeringSync_Lifecycle_ClientDeletion(t *testing.T) { s2.logger.Trace("deleted peering for my-peer-s1") retry.Run(t, func(r *retry.R) { - _, found := s2.peeringService.StreamStatus(p.ID) + _, found := s2.peerStreamServer.StreamStatus(p.ID) require.False(r, found) }) @@ -186,7 +186,7 @@ func TestLeader_PeeringSync_Lifecycle_ServerDeletion(t *testing.T) { require.NoError(t, s2.fsm.State().PeeringWrite(1000, p)) retry.Run(t, func(r *retry.R) { - status, found := s2.peeringService.StreamStatus(p.ID) + status, found := s2.peerStreamServer.StreamStatus(p.ID) require.True(r, found) require.True(r, status.Connected) }) @@ -201,7 +201,7 @@ func TestLeader_PeeringSync_Lifecycle_ServerDeletion(t *testing.T) { s2.logger.Trace("deleted peering for my-peer-s1") retry.Run(t, func(r *retry.R) { - _, found := s1.peeringService.StreamStatus(p.PeerID) + _, found := s1.peerStreamServer.StreamStatus(p.PeerID) require.False(r, found) }) diff --git a/agent/consul/peering_backend.go b/agent/consul/peering_backend.go index 047569f110..4014bbdd28 100644 --- a/agent/consul/peering_backend.go +++ b/agent/consul/peering_backend.go @@ -7,51 +7,56 @@ import ( "strconv" "sync" - "google.golang.org/grpc" - "github.com/hashicorp/consul/agent/consul/stream" + "github.com/hashicorp/consul/agent/grpc-external/services/peerstream" "github.com/hashicorp/consul/agent/rpc/peering" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/pbpeering" ) -type peeringBackend struct { +type PeeringBackend struct { // TODO(peering): accept a smaller interface; maybe just funcs from the server that we actually need: DC, IsLeader, etc - srv *Server - connPool GRPCClientConner - apply *peeringApply - addr *leaderAddr + srv *Server + + leaderAddrLock sync.RWMutex + leaderAddr string } -var _ peering.Backend = (*peeringBackend)(nil) +var _ peering.Backend = (*PeeringBackend)(nil) +var _ peerstream.Backend = (*PeeringBackend)(nil) // NewPeeringBackend returns a peering.Backend implementation that is bound to the given server. -func NewPeeringBackend(srv *Server, connPool GRPCClientConner) peering.Backend { - return &peeringBackend{ - srv: srv, - connPool: connPool, - apply: &peeringApply{srv: srv}, - addr: &leaderAddr{}, +func NewPeeringBackend(srv *Server) *PeeringBackend { + return &PeeringBackend{ + srv: srv, } } -// Forward should not be used to initiate forwarding over bidirectional streams -func (b *peeringBackend) Forward(info structs.RPCInfo, f func(*grpc.ClientConn) error) (handled bool, err error) { - // Only forward the request if the dc in the request matches the server's datacenter. - if info.RequestDatacenter() != "" && info.RequestDatacenter() != b.srv.config.Datacenter { - return false, fmt.Errorf("requests to generate peering tokens cannot be forwarded to remote datacenters") - } - return b.srv.ForwardGRPC(b.connPool, info, f) +// SetLeaderAddress is called on a raft.LeaderObservation in a go routine +// in the consul server; see trackLeaderChanges() +func (b *PeeringBackend) SetLeaderAddress(addr string) { + b.leaderAddrLock.Lock() + b.leaderAddr = addr + b.leaderAddrLock.Unlock() +} + +// GetLeaderAddress provides the best hint for the current address of the +// leader. There is no guarantee that this is the actual address of the +// leader. +func (b *PeeringBackend) GetLeaderAddress() string { + b.leaderAddrLock.RLock() + defer b.leaderAddrLock.RUnlock() + return b.leaderAddr } // GetAgentCACertificates gets the server's raw CA data from its TLS Configurator. -func (b *peeringBackend) GetAgentCACertificates() ([]string, error) { +func (b *PeeringBackend) GetAgentCACertificates() ([]string, error) { // TODO(peering): handle empty CA pems return b.srv.tlsConfigurator.ManualCAPems(), nil } // GetServerAddresses looks up server node addresses from the state store. -func (b *peeringBackend) GetServerAddresses() ([]string, error) { +func (b *PeeringBackend) GetServerAddresses() ([]string, error) { state := b.srv.fsm.State() _, nodes, err := state.ServiceNodes(nil, "consul", structs.DefaultEnterpriseMetaInDefaultPartition(), structs.DefaultPeerKeyword) if err != nil { @@ -59,19 +64,26 @@ func (b *peeringBackend) GetServerAddresses() ([]string, error) { } var addrs []string for _, node := range nodes { - addrs = append(addrs, node.Address+":"+strconv.Itoa(node.ServicePort)) + grpcPortStr := node.ServiceMeta["grpc_port"] + if v, err := strconv.Atoi(grpcPortStr); err != nil || v < 1 { + continue // skip server that isn't exporting public gRPC properly + } + addrs = append(addrs, node.Address+":"+grpcPortStr) + } + if len(addrs) == 0 { + return nil, fmt.Errorf("a grpc bind port must be specified in the configuration for all servers") } return addrs, nil } // GetServerName returns the SNI to be returned in the peering token data which // will be used by peers when establishing peering connections over TLS. -func (b *peeringBackend) GetServerName() string { +func (b *PeeringBackend) GetServerName() string { return b.srv.tlsConfigurator.ServerSNI(b.srv.config.Datacenter, "") } // EncodeToken encodes a peering token as a bas64-encoded representation of JSON (for now). -func (b *peeringBackend) EncodeToken(tok *structs.PeeringToken) ([]byte, error) { +func (b *PeeringBackend) EncodeToken(tok *structs.PeeringToken) ([]byte, error) { jsonToken, err := json.Marshal(tok) if err != nil { return nil, fmt.Errorf("failed to marshal token: %w", err) @@ -80,7 +92,7 @@ func (b *peeringBackend) EncodeToken(tok *structs.PeeringToken) ([]byte, error) } // DecodeToken decodes a peering token from a base64-encoded JSON byte array (for now). -func (b *peeringBackend) DecodeToken(tokRaw []byte) (*structs.PeeringToken, error) { +func (b *PeeringBackend) DecodeToken(tokRaw []byte) (*structs.PeeringToken, error) { tokJSONRaw, err := base64.StdEncoding.DecodeString(string(tokRaw)) if err != nil { return nil, fmt.Errorf("failed to decode token: %w", err) @@ -92,59 +104,28 @@ func (b *peeringBackend) DecodeToken(tokRaw []byte) (*structs.PeeringToken, erro return &tok, nil } -func (s peeringBackend) Subscribe(req *stream.SubscribeRequest) (*stream.Subscription, error) { +func (s *PeeringBackend) Subscribe(req *stream.SubscribeRequest) (*stream.Subscription, error) { return s.srv.publisher.Subscribe(req) } -func (b *peeringBackend) Store() peering.Store { +func (b *PeeringBackend) Store() peering.Store { return b.srv.fsm.State() } -func (b *peeringBackend) Apply() peering.Apply { - return b.apply -} - -func (b *peeringBackend) LeaderAddress() peering.LeaderAddress { - return b.addr -} - -func (b *peeringBackend) EnterpriseCheckPartitions(partition string) error { +func (b *PeeringBackend) EnterpriseCheckPartitions(partition string) error { return b.enterpriseCheckPartitions(partition) } -func (b *peeringBackend) EnterpriseCheckNamespaces(namespace string) error { +func (b *PeeringBackend) EnterpriseCheckNamespaces(namespace string) error { return b.enterpriseCheckNamespaces(namespace) } -func (b *peeringBackend) IsLeader() bool { +func (b *PeeringBackend) IsLeader() bool { return b.srv.IsLeader() } -type leaderAddr struct { - lock sync.RWMutex - leaderAddr string -} - -func (m *leaderAddr) Set(addr string) { - m.lock.Lock() - defer m.lock.Unlock() - - m.leaderAddr = addr -} - -func (m *leaderAddr) Get() string { - m.lock.RLock() - defer m.lock.RUnlock() - - return m.leaderAddr -} - -type peeringApply struct { - srv *Server -} - -func (a *peeringApply) CheckPeeringUUID(id string) (bool, error) { - state := a.srv.fsm.State() +func (b *PeeringBackend) CheckPeeringUUID(id string) (bool, error) { + state := b.srv.fsm.State() if _, existing, err := state.PeeringReadByID(nil, id); err != nil { return false, err } else if existing != nil { @@ -154,31 +135,28 @@ func (a *peeringApply) CheckPeeringUUID(id string) (bool, error) { return true, nil } -func (a *peeringApply) PeeringWrite(req *pbpeering.PeeringWriteRequest) error { - _, err := a.srv.raftApplyProtobuf(structs.PeeringWriteType, req) +func (b *PeeringBackend) PeeringWrite(req *pbpeering.PeeringWriteRequest) error { + _, err := b.srv.raftApplyProtobuf(structs.PeeringWriteType, req) return err } // TODO(peering): This needs RPC metrics interceptor since it's not triggered by an RPC. -func (a *peeringApply) PeeringTerminateByID(req *pbpeering.PeeringTerminateByIDRequest) error { - _, err := a.srv.raftApplyProtobuf(structs.PeeringTerminateByIDType, req) +func (b *PeeringBackend) PeeringTerminateByID(req *pbpeering.PeeringTerminateByIDRequest) error { + _, err := b.srv.raftApplyProtobuf(structs.PeeringTerminateByIDType, req) return err } -func (a *peeringApply) PeeringTrustBundleWrite(req *pbpeering.PeeringTrustBundleWriteRequest) error { - _, err := a.srv.raftApplyProtobuf(structs.PeeringTrustBundleWriteType, req) +func (b *PeeringBackend) PeeringTrustBundleWrite(req *pbpeering.PeeringTrustBundleWriteRequest) error { + _, err := b.srv.raftApplyProtobuf(structs.PeeringTrustBundleWriteType, req) return err } -func (a *peeringApply) CatalogRegister(req *structs.RegisterRequest) error { - _, err := a.srv.leaderRaftApply("Catalog.Register", structs.RegisterRequestType, req) +func (b *PeeringBackend) CatalogRegister(req *structs.RegisterRequest) error { + _, err := b.srv.leaderRaftApply("Catalog.Register", structs.RegisterRequestType, req) return err } -func (a *peeringApply) CatalogDeregister(req *structs.DeregisterRequest) error { - _, err := a.srv.leaderRaftApply("Catalog.Deregister", structs.DeregisterRequestType, req) +func (b *PeeringBackend) CatalogDeregister(req *structs.DeregisterRequest) error { + _, err := b.srv.leaderRaftApply("Catalog.Deregister", structs.DeregisterRequestType, req) return err } - -var _ peering.Apply = (*peeringApply)(nil) -var _ peering.LeaderAddress = (*leaderAddr)(nil) diff --git a/agent/consul/peering_backend_oss.go b/agent/consul/peering_backend_oss.go index 412ce34a24..18d567b3c1 100644 --- a/agent/consul/peering_backend_oss.go +++ b/agent/consul/peering_backend_oss.go @@ -8,14 +8,14 @@ import ( "strings" ) -func (b *peeringBackend) enterpriseCheckPartitions(partition string) error { +func (b *PeeringBackend) enterpriseCheckPartitions(partition string) error { if partition == "" || strings.EqualFold(partition, "default") { return nil } return fmt.Errorf("Partitions are a Consul Enterprise feature") } -func (b *peeringBackend) enterpriseCheckNamespaces(namespace string) error { +func (b *PeeringBackend) enterpriseCheckNamespaces(namespace string) error { if namespace == "" || strings.EqualFold(namespace, "default") { return nil } diff --git a/agent/consul/rpc_test.go b/agent/consul/rpc_test.go index 64da9a389e..1e9239d92b 100644 --- a/agent/consul/rpc_test.go +++ b/agent/consul/rpc_test.go @@ -32,7 +32,7 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/state" - agent_grpc "github.com/hashicorp/consul/agent/grpc/private" + agent_grpc "github.com/hashicorp/consul/agent/grpc-internal" "github.com/hashicorp/consul/agent/pool" "github.com/hashicorp/consul/agent/structs" tokenStore "github.com/hashicorp/consul/agent/token" diff --git a/agent/consul/server.go b/agent/consul/server.go index ba198ce6bf..a5708e030f 100644 --- a/agent/consul/server.go +++ b/agent/consul/server.go @@ -39,12 +39,13 @@ import ( "github.com/hashicorp/consul/agent/consul/stream" "github.com/hashicorp/consul/agent/consul/usagemetrics" "github.com/hashicorp/consul/agent/consul/wanfed" - agentgrpc "github.com/hashicorp/consul/agent/grpc/private" - "github.com/hashicorp/consul/agent/grpc/private/services/subscribe" - aclgrpc "github.com/hashicorp/consul/agent/grpc/public/services/acl" - "github.com/hashicorp/consul/agent/grpc/public/services/connectca" - "github.com/hashicorp/consul/agent/grpc/public/services/dataplane" - "github.com/hashicorp/consul/agent/grpc/public/services/serverdiscovery" + aclgrpc "github.com/hashicorp/consul/agent/grpc-external/services/acl" + "github.com/hashicorp/consul/agent/grpc-external/services/connectca" + "github.com/hashicorp/consul/agent/grpc-external/services/dataplane" + "github.com/hashicorp/consul/agent/grpc-external/services/peerstream" + "github.com/hashicorp/consul/agent/grpc-external/services/serverdiscovery" + agentgrpc "github.com/hashicorp/consul/agent/grpc-internal" + "github.com/hashicorp/consul/agent/grpc-internal/services/subscribe" "github.com/hashicorp/consul/agent/metadata" "github.com/hashicorp/consul/agent/pool" "github.com/hashicorp/consul/agent/router" @@ -55,7 +56,6 @@ import ( "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib/routine" "github.com/hashicorp/consul/logging" - "github.com/hashicorp/consul/proto/pbpeering" "github.com/hashicorp/consul/proto/pbsubscribe" "github.com/hashicorp/consul/tlsutil" "github.com/hashicorp/consul/types" @@ -242,19 +242,19 @@ type Server struct { // is only ever closed. leaveCh chan struct{} - // publicACLServer serves the ACL service exposed on the public gRPC port. - // It is also exposed on the private multiplexed "server" port to enable + // externalACLServer serves the ACL service exposed on the external gRPC port. + // It is also exposed on the internal multiplexed "server" port to enable // RPC forwarding. - publicACLServer *aclgrpc.Server + externalACLServer *aclgrpc.Server - // publicConnectCAServer serves the Connect CA service exposed on the public - // gRPC port. It is also exposed on the private multiplexed "server" port to + // externalConnectCAServer serves the Connect CA service exposed on the external + // gRPC port. It is also exposed on the internal multiplexed "server" port to // enable RPC forwarding. - publicConnectCAServer *connectca.Server + externalConnectCAServer *connectca.Server - // publicGRPCServer is the gRPC server exposed on the dedicated gRPC port, as + // externalGRPCServer is the gRPC server exposed on the dedicated gRPC port, as // opposed to the multiplexed "server" port which is served by grpcHandler. - publicGRPCServer *grpc.Server + externalGRPCServer *grpc.Server // router is used to map out Consul servers in the WAN and in Consul // Enterprise user-defined areas. @@ -364,8 +364,13 @@ type Server struct { // this into the Deps struct and created it much earlier on. publisher *stream.EventPublisher - // peering is a service used to handle peering streams. - peeringService *peering.Service + // peeringBackend is shared between the external and internal gRPC services for peering + peeringBackend *PeeringBackend + + // peerStreamServer is a server used to handle peering streams + peerStreamServer *peerstream.Server + peeringServer *peering.Server + peerStreamTracker *peerstream.Tracker // embedded struct to hold all the enterprise specific data EnterpriseServer @@ -379,7 +384,7 @@ type connHandler interface { // NewServer is used to construct a new Consul server from the configuration // and extra options, potentially returning an error. -func NewServer(config *Config, flat Deps, publicGRPCServer *grpc.Server) (*Server, error) { +func NewServer(config *Config, flat Deps, externalGRPCServer *grpc.Server) (*Server, error) { logger := flat.Logger if err := config.CheckProtocolVersion(); err != nil { return nil, err @@ -425,7 +430,7 @@ func NewServer(config *Config, flat Deps, publicGRPCServer *grpc.Server) (*Serve reconcileCh: make(chan serf.Member, reconcileChSize), router: flat.Router, tlsConfigurator: flat.TLSConfigurator, - publicGRPCServer: publicGRPCServer, + externalGRPCServer: externalGRPCServer, reassertLeaderCh: make(chan chan error), sessionTimers: NewSessionTimers(), tombstoneGC: gc, @@ -672,8 +677,8 @@ func NewServer(config *Config, flat Deps, publicGRPCServer *grpc.Server) (*Serve s.overviewManager = NewOverviewManager(s.logger, s.fsm, s.config.MetricsReportingInterval) go s.overviewManager.Run(&lib.StopChannelContext{StopCh: s.shutdownCh}) - // Initialize public gRPC server - register services on public gRPC server. - s.publicACLServer = aclgrpc.NewServer(aclgrpc.Config{ + // Initialize external gRPC server - register services on external gRPC server. + s.externalACLServer = aclgrpc.NewServer(aclgrpc.Config{ ACLsEnabled: s.config.ACLsEnabled, ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { return s.ForwardGRPC(s.grpcConnPool, info, fn) @@ -689,9 +694,9 @@ func NewServer(config *Config, flat Deps, publicGRPCServer *grpc.Server) (*Serve PrimaryDatacenter: s.config.PrimaryDatacenter, ValidateEnterpriseRequest: s.validateEnterpriseRequest, }) - s.publicACLServer.Register(s.publicGRPCServer) + s.externalACLServer.Register(s.externalGRPCServer) - s.publicConnectCAServer = connectca.NewServer(connectca.Config{ + s.externalConnectCAServer = connectca.NewServer(connectca.Config{ Publisher: s.publisher, GetStore: func() connectca.StateStore { return s.FSM().State() }, Logger: logger.Named("grpc-api.connect-ca"), @@ -702,24 +707,37 @@ func NewServer(config *Config, flat Deps, publicGRPCServer *grpc.Server) (*Serve }, ConnectEnabled: s.config.ConnectEnabled, }) - s.publicConnectCAServer.Register(s.publicGRPCServer) + s.externalConnectCAServer.Register(s.externalGRPCServer) dataplane.NewServer(dataplane.Config{ GetStore: func() dataplane.StateStore { return s.FSM().State() }, Logger: logger.Named("grpc-api.dataplane"), ACLResolver: s.ACLResolver, Datacenter: s.config.Datacenter, - }).Register(s.publicGRPCServer) + }).Register(s.externalGRPCServer) serverdiscovery.NewServer(serverdiscovery.Config{ Publisher: s.publisher, ACLResolver: s.ACLResolver, Logger: logger.Named("grpc-api.server-discovery"), - }).Register(s.publicGRPCServer) + }).Register(s.externalGRPCServer) - // Initialize private gRPC server. + s.peerStreamTracker = peerstream.NewTracker() + s.peeringBackend = NewPeeringBackend(s) + s.peerStreamServer = peerstream.NewServer(peerstream.Config{ + Backend: s.peeringBackend, + Tracker: s.peerStreamTracker, + GetStore: func() peerstream.StateStore { return s.FSM().State() }, + Logger: logger.Named("grpc-api.peerstream"), + ACLResolver: s.ACLResolver, + Datacenter: s.config.Datacenter, + ConnectEnabled: s.config.ConnectEnabled, + }) + s.peerStreamServer.Register(s.externalGRPCServer) + + // Initialize internal gRPC server. // - // Note: some "public" gRPC services are also exposed on the private gRPC server + // Note: some "external" gRPC services are also exposed on the internal gRPC server // to enable RPC forwarding. s.grpcHandler = newGRPCHandlerFromConfig(flat, config, s) s.grpcLeaderForwarder = flat.LeaderForwarder @@ -757,15 +775,25 @@ func NewServer(config *Config, flat Deps, publicGRPCServer *grpc.Server) (*Serve } func newGRPCHandlerFromConfig(deps Deps, config *Config, s *Server) connHandler { - p := peering.NewService( - deps.Logger.Named("grpc-api.peering"), - peering.Config{ - Datacenter: config.Datacenter, - ConnectEnabled: config.ConnectEnabled, + if s.peeringBackend == nil { + panic("peeringBackend is required during construction") + } + + p := peering.NewServer(peering.Config{ + Backend: s.peeringBackend, + Tracker: s.peerStreamTracker, + Logger: deps.Logger.Named("grpc-api.peering"), + ForwardRPC: func(info structs.RPCInfo, fn func(*grpc.ClientConn) error) (bool, error) { + // Only forward the request if the dc in the request matches the server's datacenter. + if info.RequestDatacenter() != "" && info.RequestDatacenter() != config.Datacenter { + return false, fmt.Errorf("requests to generate peering tokens cannot be forwarded to remote datacenters") + } + return s.ForwardGRPC(s.grpcConnPool, info, fn) }, - NewPeeringBackend(s, deps.GRPCConnPool), - ) - s.peeringService = p + Datacenter: config.Datacenter, + ConnectEnabled: config.ConnectEnabled, + }) + s.peeringServer = p register := func(srv *grpc.Server) { if config.RPCConfig.EnableStreaming { @@ -773,13 +801,13 @@ func newGRPCHandlerFromConfig(deps Deps, config *Config, s *Server) connHandler &subscribeBackend{srv: s, connPool: deps.GRPCConnPool}, deps.Logger.Named("grpc-api.subscription"))) } - pbpeering.RegisterPeeringServiceServer(srv, s.peeringService) + s.peeringServer.Register(srv) s.registerEnterpriseGRPCServices(deps, srv) - // Note: these public gRPC services are also exposed on the private server to + // Note: these external gRPC services are also exposed on the internal server to // enable RPC forwarding. - s.publicACLServer.Register(srv) - s.publicConnectCAServer.Register(srv) + s.externalACLServer.Register(srv) + s.externalConnectCAServer.Register(srv) } return agentgrpc.NewHandler(deps.Logger, config.RPCAddr, register) @@ -1658,7 +1686,7 @@ func (s *Server) trackLeaderChanges() { } s.grpcLeaderForwarder.UpdateLeaderAddr(s.config.Datacenter, string(leaderObs.LeaderAddr)) - s.peeringService.Backend.LeaderAddress().Set(string(leaderObs.LeaderAddr)) + s.peeringBackend.SetLeaderAddress(string(leaderObs.LeaderAddr)) case <-s.shutdownCh: s.raft.DeregisterObserver(observer) return diff --git a/agent/consul/server_serf.go b/agent/consul/server_serf.go index 3db25c155f..5e29b47dd2 100644 --- a/agent/consul/server_serf.go +++ b/agent/consul/server_serf.go @@ -103,6 +103,9 @@ func (s *Server) setupSerfConfig(opts setupSerfOptions) (*serf.Config, error) { conf.Tags["build"] = s.config.Build addr := opts.Listener.Addr().(*net.TCPAddr) conf.Tags["port"] = fmt.Sprintf("%d", addr.Port) + if s.config.GRPCPort > 0 { + conf.Tags["grpc_port"] = fmt.Sprintf("%d", s.config.GRPCPort) + } if s.config.Bootstrap { conf.Tags["bootstrap"] = "1" } diff --git a/agent/consul/server_test.go b/agent/consul/server_test.go index c2d9c96c2f..77f761f683 100644 --- a/agent/consul/server_test.go +++ b/agent/consul/server_test.go @@ -15,12 +15,12 @@ import ( "github.com/armon/go-metrics" "github.com/google/tcpproxy" "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-uuid" "github.com/hashicorp/memberlist" "github.com/hashicorp/raft" - "google.golang.org/grpc" - - "github.com/hashicorp/go-uuid" + "github.com/stretchr/testify/require" "golang.org/x/time/rate" + "google.golang.org/grpc" "github.com/hashicorp/consul-net-rpc/net/rpc" @@ -36,8 +36,6 @@ import ( "github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/tlsutil" "github.com/hashicorp/consul/types" - - "github.com/stretchr/testify/require" ) const ( @@ -111,7 +109,7 @@ func testServerConfig(t *testing.T) (string, *Config) { dir := testutil.TempDir(t, "consul") config := DefaultConfig() - ports := freeport.GetN(t, 3) + ports := freeport.GetN(t, 4) // {server, serf_lan, serf_wan, grpc} config.NodeName = uniqueNodeName(t.Name()) config.Bootstrap = true config.Datacenter = "dc1" @@ -167,6 +165,8 @@ func testServerConfig(t *testing.T) (string, *Config) { // looks like several depend on it. config.RPCHoldTimeout = 10 * time.Second + config.GRPCPort = ports[3] + config.ConnectEnabled = true config.CAConfig = &structs.CAConfiguration{ ClusterID: connect.TestClusterID, @@ -239,6 +239,19 @@ func testServerWithConfig(t *testing.T, configOpts ...func(*Config)) (string, *S }) t.Cleanup(func() { srv.Shutdown() }) + if srv.config.GRPCPort > 0 { + // Normally the gRPC server listener is created at the agent level and + // passed down into the Server creation. + externalGRPCAddr := fmt.Sprintf("127.0.0.1:%d", srv.config.GRPCPort) + + ln, err := net.Listen("tcp", externalGRPCAddr) + require.NoError(t, err) + go func() { + _ = srv.externalGRPCServer.Serve(ln) + }() + t.Cleanup(srv.externalGRPCServer.Stop) + } + return dir, srv } @@ -262,16 +275,8 @@ func testACLServerWithConfig(t *testing.T, cb func(*Config), initReplicationToke func testGRPCIntegrationServer(t *testing.T, cb func(*Config)) (*Server, *grpc.ClientConn, rpc.ClientCodec) { _, srv, codec := testACLServerWithConfig(t, cb, false) - // Normally the gRPC server listener is created at the agent level and passed down into - // the Server creation. For our tests, we need to ensure - ln, err := net.Listen("tcp", "127.0.0.1:0") - require.NoError(t, err) - go func() { - _ = srv.publicGRPCServer.Serve(ln) - }() - t.Cleanup(srv.publicGRPCServer.Stop) - - conn, err := grpc.Dial(ln.Addr().String(), grpc.WithInsecure()) + grpcAddr := fmt.Sprintf("127.0.0.1:%d", srv.config.GRPCPort) + conn, err := grpc.Dial(grpcAddr, grpc.WithInsecure()) require.NoError(t, err) t.Cleanup(func() { _ = conn.Close() }) @@ -1992,7 +1997,7 @@ func TestServer_Peering_LeadershipCheck(t *testing.T) { // the actual tests // when leadership has been established s2 should have the address of s1 // in the peering service - peeringLeaderAddr := s2.peeringService.Backend.LeaderAddress().Get() + peeringLeaderAddr := s2.peeringBackend.GetLeaderAddress() require.Equal(t, s1.config.RPCAddr.String(), peeringLeaderAddr) // test corollary by transitivity to future-proof against any setup bugs diff --git a/agent/consul/state/config_entry.go b/agent/consul/state/config_entry.go index 02731d1b09..af0fe21133 100644 --- a/agent/consul/state/config_entry.go +++ b/agent/consul/state/config_entry.go @@ -138,7 +138,12 @@ func (s *Store) ConfigEntriesByKind(ws memdb.WatchSet, kind string, entMeta *acl return configEntriesByKindTxn(tx, ws, kind, entMeta) } -func listDiscoveryChainNamesTxn(tx ReadTxn, ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []structs.ServiceName, error) { +func listDiscoveryChainNamesTxn( + tx ReadTxn, + ws memdb.WatchSet, + overrides map[configentry.KindName]structs.ConfigEntry, + entMeta acl.EnterpriseMeta, +) (uint64, []structs.ServiceName, error) { // Get the index and watch for updates idx := maxIndexWatchTxn(tx, ws, tableConfigEntries) @@ -160,6 +165,15 @@ func listDiscoveryChainNamesTxn(tx ReadTxn, ws memdb.WatchSet, entMeta acl.Enter sn := structs.NewServiceName(entry.GetName(), entry.GetEnterpriseMeta()) seen[sn] = struct{}{} } + + for kn, entry := range overrides { + sn := structs.NewServiceName(kn.Name, &kn.EnterpriseMeta) + if entry != nil { + seen[sn] = struct{}{} + } else { + delete(seen, sn) + } + } } results := maps.SliceOfKeys(seen) @@ -506,7 +520,7 @@ var serviceGraphKinds = []string{ // discoveryChainTargets will return a list of services listed as a target for the input's discovery chain func (s *Store) discoveryChainTargetsTxn(tx ReadTxn, ws memdb.WatchSet, dc, service string, entMeta *acl.EnterpriseMeta) (uint64, []structs.ServiceName, error) { - idx, targets, err := s.discoveryChainOriginalTargetsTxn(tx, ws, dc, service, entMeta) + idx, targets, err := discoveryChainOriginalTargetsTxn(tx, ws, dc, service, entMeta) if err != nil { return 0, nil, err } @@ -524,7 +538,12 @@ func (s *Store) discoveryChainTargetsTxn(tx ReadTxn, ws memdb.WatchSet, dc, serv return idx, resp, nil } -func (s *Store) discoveryChainOriginalTargetsTxn(tx ReadTxn, ws memdb.WatchSet, dc, service string, entMeta *acl.EnterpriseMeta) (uint64, []*structs.DiscoveryTarget, error) { +func discoveryChainOriginalTargetsTxn( + tx ReadTxn, + ws memdb.WatchSet, + dc, service string, + entMeta *acl.EnterpriseMeta, +) (uint64, []*structs.DiscoveryTarget, error) { source := structs.NewServiceName(service, entMeta) req := discoverychain.CompileRequest{ ServiceName: source.Name, @@ -532,7 +551,7 @@ func (s *Store) discoveryChainOriginalTargetsTxn(tx ReadTxn, ws memdb.WatchSet, EvaluateInPartition: source.PartitionOrDefault(), EvaluateInDatacenter: dc, } - idx, chain, _, err := s.serviceDiscoveryChainTxn(tx, ws, source.Name, entMeta, req) + idx, chain, _, err := serviceDiscoveryChainTxn(tx, ws, source.Name, entMeta, req) if err != nil { return 0, nil, fmt.Errorf("failed to fetch discovery chain for %q: %v", source.String(), err) } @@ -579,7 +598,7 @@ func (s *Store) discoveryChainSourcesTxn(tx ReadTxn, ws memdb.WatchSet, dc strin EvaluateInPartition: sn.PartitionOrDefault(), EvaluateInDatacenter: dc, } - idx, chain, _, err := s.serviceDiscoveryChainTxn(tx, ws, sn.Name, &sn.EnterpriseMeta, req) + idx, chain, _, err := serviceDiscoveryChainTxn(tx, ws, sn.Name, &sn.EnterpriseMeta, req) if err != nil { return 0, nil, fmt.Errorf("failed to fetch discovery chain for %q: %v", sn.String(), err) } @@ -620,7 +639,28 @@ func validateProposedConfigEntryInServiceGraph( wildcardEntMeta := kindName.WithWildcardNamespace() switch kindName.Kind { - case structs.ExportedServices, structs.MeshConfig: + case structs.ExportedServices: + // This is the case for deleting a config entry + if newEntry == nil { + return nil + } + + entry := newEntry.(*structs.ExportedServicesConfigEntry) + + _, serviceList, err := listServicesExportedToAnyPeerByConfigEntry(nil, tx, entry, nil) + if err != nil { + return err + } + + for _, sn := range serviceList { + if err := validateChainIsPeerExportSafe(tx, sn, nil); err != nil { + return err + } + } + + return nil + + case structs.MeshConfig: // Exported services and mesh config do not influence discovery chains. return nil @@ -759,16 +799,59 @@ func validateProposedConfigEntryInServiceGraph( } var ( - svcProtocols = make(map[structs.ServiceID]string) - svcTopNodeType = make(map[structs.ServiceID]string) + svcProtocols = make(map[structs.ServiceID]string) + svcTopNodeType = make(map[structs.ServiceID]string) + exportedServicesByPartition = make(map[string]map[structs.ServiceName]struct{}) ) for chain := range checkChains { - protocol, topNode, err := testCompileDiscoveryChain(tx, chain.ID, overrides, &chain.EnterpriseMeta) + protocol, topNode, newTargets, err := testCompileDiscoveryChain(tx, chain.ID, overrides, &chain.EnterpriseMeta) if err != nil { return err } svcProtocols[chain] = protocol svcTopNodeType[chain] = topNode.Type + + chainSvc := structs.NewServiceName(chain.ID, &chain.EnterpriseMeta) + + // Validate that we aren't adding a cross-datacenter or cross-partition + // reference to a peer-exported service's discovery chain by this pending + // edit. + partition := chain.PartitionOrDefault() + exportedServices, ok := exportedServicesByPartition[partition] + if !ok { + entMeta := structs.NodeEnterpriseMetaInPartition(partition) + _, exportedServices, err = listAllExportedServices(nil, tx, overrides, *entMeta) + if err != nil { + return err + } + exportedServicesByPartition[partition] = exportedServices + } + if _, exported := exportedServices[chainSvc]; exported { + if err := validateChainIsPeerExportSafe(tx, chainSvc, overrides); err != nil { + return err + } + + // If a TCP (L4) discovery chain is peer exported we have to take + // care to prohibit certain edits to service-resolvers. + if !structs.IsProtocolHTTPLike(protocol) { + _, _, oldTargets, err := testCompileDiscoveryChain(tx, chain.ID, nil, &chain.EnterpriseMeta) + if err != nil { + return fmt.Errorf("error compiling current discovery chain for %q: %w", chainSvc, err) + } + + // Ensure that you can't introduce any new targets that would + // produce a new SpiffeID for this L4 service. + oldSpiffeIDs := convertTargetsToTestSpiffeIDs(oldTargets) + newSpiffeIDs := convertTargetsToTestSpiffeIDs(newTargets) + for id, targetID := range newSpiffeIDs { + if _, exists := oldSpiffeIDs[id]; !exists { + return fmt.Errorf("peer exported service %q uses protocol=%q and cannot introduce new discovery chain targets like %q", + chainSvc, protocol, targetID, + ) + } + } + } + } } // Now validate all of our ingress gateways. @@ -828,18 +911,84 @@ func validateProposedConfigEntryInServiceGraph( return nil } +func validateChainIsPeerExportSafe( + tx ReadTxn, + exportedSvc structs.ServiceName, + overrides map[configentry.KindName]structs.ConfigEntry, +) error { + _, chainEntries, err := readDiscoveryChainConfigEntriesTxn(tx, nil, exportedSvc.Name, overrides, &exportedSvc.EnterpriseMeta) + if err != nil { + return fmt.Errorf("error reading discovery chain for %q during config entry validation: %w", exportedSvc, err) + } + + emptyOrMatchesEntryPartition := func(entry structs.ConfigEntry, found string) bool { + if found == "" { + return true + } + return acl.EqualPartitions(entry.GetEnterpriseMeta().PartitionOrEmpty(), found) + } + + for _, e := range chainEntries.Routers { + for _, route := range e.Routes { + if route.Destination == nil { + continue + } + if !emptyOrMatchesEntryPartition(e, route.Destination.Partition) { + return fmt.Errorf("peer exported service %q contains cross-partition route destination", exportedSvc) + } + } + } + + for _, e := range chainEntries.Splitters { + for _, split := range e.Splits { + if !emptyOrMatchesEntryPartition(e, split.Partition) { + return fmt.Errorf("peer exported service %q contains cross-partition split destination", exportedSvc) + } + } + } + + for _, e := range chainEntries.Resolvers { + if e.Redirect != nil { + if e.Redirect.Datacenter != "" { + return fmt.Errorf("peer exported service %q contains cross-datacenter resolver redirect", exportedSvc) + } + if !emptyOrMatchesEntryPartition(e, e.Redirect.Partition) { + return fmt.Errorf("peer exported service %q contains cross-partition resolver redirect", exportedSvc) + } + } + if e.Failover != nil { + for _, failover := range e.Failover { + if len(failover.Datacenters) > 0 { + return fmt.Errorf("peer exported service %q contains cross-datacenter failover", exportedSvc) + } + } + } + } + + return nil +} + // testCompileDiscoveryChain speculatively compiles a discovery chain with // pending modifications to see if it would be valid. Also returns the computed // protocol and topmost discovery chain node. +// +// If provided, the overrides map will service reads of specific config entries +// instead of the state store if the config entry kind name is present in the +// map. A nil in the map implies that the config entry should be tombstoned +// during evaluation and treated as erased. +// +// The override map lets us speculatively compile a discovery chain to see if +// doing so would error, so we can ultimately block config entry writes from +// happening. func testCompileDiscoveryChain( tx ReadTxn, chainName string, overrides map[configentry.KindName]structs.ConfigEntry, entMeta *acl.EnterpriseMeta, -) (string, *structs.DiscoveryGraphNode, error) { +) (string, *structs.DiscoveryGraphNode, map[string]*structs.DiscoveryTarget, error) { _, speculativeEntries, err := readDiscoveryChainConfigEntriesTxn(tx, nil, chainName, overrides, entMeta) if err != nil { - return "", nil, err + return "", nil, nil, err } // Note we use an arbitrary namespace and datacenter as those would not @@ -856,10 +1005,10 @@ func testCompileDiscoveryChain( } chain, err := discoverychain.Compile(req) if err != nil { - return "", nil, err + return "", nil, nil, err } - return chain.Protocol, chain.Nodes[chain.StartNode], nil + return chain.Protocol, chain.Nodes[chain.StartNode], chain.Targets, nil } func (s *Store) ServiceDiscoveryChain( @@ -871,10 +1020,10 @@ func (s *Store) ServiceDiscoveryChain( tx := s.db.ReadTxn() defer tx.Abort() - return s.serviceDiscoveryChainTxn(tx, ws, serviceName, entMeta, req) + return serviceDiscoveryChainTxn(tx, ws, serviceName, entMeta, req) } -func (s *Store) serviceDiscoveryChainTxn( +func serviceDiscoveryChainTxn( tx ReadTxn, ws memdb.WatchSet, serviceName string, @@ -888,7 +1037,7 @@ func (s *Store) serviceDiscoveryChainTxn( } req.Entries = entries - _, config, err := s.CAConfig(ws) + _, config, err := caConfigTxn(tx, ws) if err != nil { return 0, nil, nil, err } else if config == nil { @@ -1268,7 +1417,9 @@ func anyKey(m map[structs.ServiceID]struct{}) (structs.ServiceID, bool) { // getProxyConfigEntryTxn is a convenience method for fetching a // proxy-defaults kind of config entry. // -// If an override is returned the index returned will be 0. +// If an override KEY is present for the requested config entry, the index +// returned will be 0. Any override VALUE (nil or otherwise) will be returned +// if there is a KEY match. func getProxyConfigEntryTxn( tx ReadTxn, ws memdb.WatchSet, @@ -1293,7 +1444,9 @@ func getProxyConfigEntryTxn( // getServiceConfigEntryTxn is a convenience method for fetching a // service-defaults kind of config entry. // -// If an override is returned the index returned will be 0. +// If an override KEY is present for the requested config entry, the index +// returned will be 0. Any override VALUE (nil or otherwise) will be returned +// if there is a KEY match. func getServiceConfigEntryTxn( tx ReadTxn, ws memdb.WatchSet, @@ -1318,7 +1471,9 @@ func getServiceConfigEntryTxn( // getRouterConfigEntryTxn is a convenience method for fetching a // service-router kind of config entry. // -// If an override is returned the index returned will be 0. +// If an override KEY is present for the requested config entry, the index +// returned will be 0. Any override VALUE (nil or otherwise) will be returned +// if there is a KEY match. func getRouterConfigEntryTxn( tx ReadTxn, ws memdb.WatchSet, @@ -1343,7 +1498,9 @@ func getRouterConfigEntryTxn( // getSplitterConfigEntryTxn is a convenience method for fetching a // service-splitter kind of config entry. // -// If an override is returned the index returned will be 0. +// If an override KEY is present for the requested config entry, the index +// returned will be 0. Any override VALUE (nil or otherwise) will be returned +// if there is a KEY match. func getSplitterConfigEntryTxn( tx ReadTxn, ws memdb.WatchSet, @@ -1368,7 +1525,9 @@ func getSplitterConfigEntryTxn( // getResolverConfigEntryTxn is a convenience method for fetching a // service-resolver kind of config entry. // -// If an override is returned the index returned will be 0. +// If an override KEY is present for the requested config entry, the index +// returned will be 0. Any override VALUE (nil or otherwise) will be returned +// if there is a KEY match. func getResolverConfigEntryTxn( tx ReadTxn, ws memdb.WatchSet, @@ -1393,7 +1552,9 @@ func getResolverConfigEntryTxn( // getServiceIntentionsConfigEntryTxn is a convenience method for fetching a // service-intentions kind of config entry. // -// If an override is returned the index returned will be 0. +// If an override KEY is present for the requested config entry, the index +// returned will be 0. Any override VALUE (nil or otherwise) will be returned +// if there is a KEY match. func getServiceIntentionsConfigEntryTxn( tx ReadTxn, ws memdb.WatchSet, @@ -1415,6 +1576,32 @@ func getServiceIntentionsConfigEntryTxn( return idx, ixn, nil } +// getExportedServicesConfigEntryTxn is a convenience method for fetching a +// exported-services kind of config entry. +// +// If an override KEY is present for the requested config entry, the index +// returned will be 0. Any override VALUE (nil or otherwise) will be returned +// if there is a KEY match. +func getExportedServicesConfigEntryTxn( + tx ReadTxn, + ws memdb.WatchSet, + overrides map[configentry.KindName]structs.ConfigEntry, + entMeta *acl.EnterpriseMeta, +) (uint64, *structs.ExportedServicesConfigEntry, error) { + idx, entry, err := configEntryWithOverridesTxn(tx, ws, structs.ExportedServices, entMeta.PartitionOrDefault(), overrides, entMeta) + if err != nil { + return 0, nil, err + } else if entry == nil { + return idx, nil, nil + } + + export, ok := entry.(*structs.ExportedServicesConfigEntry) + if !ok { + return 0, nil, fmt.Errorf("invalid service config type %T", entry) + } + return idx, export, nil +} + func configEntryWithOverridesTxn( tx ReadTxn, ws memdb.WatchSet, @@ -1443,12 +1630,12 @@ func protocolForService( svc structs.ServiceName, ) (uint64, string, error) { // Get the global proxy defaults (for default protocol) - maxIdx, proxyConfig, err := configEntryTxn(tx, ws, structs.ProxyDefaults, structs.ProxyConfigGlobal, &svc.EnterpriseMeta) + maxIdx, proxyConfig, err := getProxyConfigEntryTxn(tx, ws, structs.ProxyConfigGlobal, nil, &svc.EnterpriseMeta) if err != nil { return 0, "", err } - idx, serviceDefaults, err := configEntryTxn(tx, ws, structs.ServiceDefaults, svc.Name, &svc.EnterpriseMeta) + idx, serviceDefaults, err := getServiceConfigEntryTxn(tx, ws, svc.Name, nil, &svc.EnterpriseMeta) if err != nil { return 0, "", err } @@ -1467,7 +1654,7 @@ func protocolForService( EvaluateInPartition: svc.PartitionOrDefault(), EvaluateInDatacenter: "dc1", // Use a dummy trust domain since that won't affect the protocol here. - EvaluateInTrustDomain: "b6fc9da3-03d4-4b5a-9134-c045e9b20152.consul", + EvaluateInTrustDomain: dummyTrustDomain, Entries: entries, } chain, err := discoverychain.Compile(req) @@ -1477,6 +1664,8 @@ func protocolForService( return maxIdx, chain.Protocol, nil } +const dummyTrustDomain = "b6fc9da3-03d4-4b5a-9134-c045e9b20152.consul" + func newConfigEntryQuery(c structs.ConfigEntry) configentry.KindName { return configentry.NewKindName(c.GetKind(), c.GetName(), c.GetEnterpriseMeta()) } @@ -1498,3 +1687,24 @@ func (q ConfigEntryKindQuery) NamespaceOrDefault() string { func (q ConfigEntryKindQuery) PartitionOrDefault() string { return q.EnterpriseMeta.PartitionOrDefault() } + +// convertTargetsToTestSpiffeIDs indexes the provided targets by their eventual +// spiffeid values using a dummy trust domain. Returns a map of SpiffeIDs to +// targetID values which can be used for error output. +func convertTargetsToTestSpiffeIDs(targets map[string]*structs.DiscoveryTarget) map[string]string { + out := make(map[string]string) + for tid, t := range targets { + testSpiffeID := connect.SpiffeIDService{ + Host: dummyTrustDomain, + Partition: t.Partition, + Namespace: t.Namespace, + Datacenter: t.Datacenter, + Service: t.Service, + } + uri := testSpiffeID.URI().String() + if _, ok := out[uri]; !ok { + out[uri] = tid + } + } + return out +} diff --git a/agent/consul/state/config_entry_test.go b/agent/consul/state/config_entry_test.go index b874f41af5..78140d021b 100644 --- a/agent/consul/state/config_entry_test.go +++ b/agent/consul/state/config_entry_test.go @@ -843,24 +843,75 @@ func TestStore_Service_TerminatingGateway_Kind_Service_Destination_Wildcard(t *t } func TestStore_ConfigEntry_GraphValidation(t *testing.T) { + ensureConfigEntry := func(s *Store, idx uint64, entry structs.ConfigEntry) error { + if err := entry.Normalize(); err != nil { + return err + } + if err := entry.Validate(); err != nil { + return err + } + return s.EnsureConfigEntry(0, entry) + } + type tcase struct { entries []structs.ConfigEntry - op func(t *testing.T, s *Store) error + opAdd structs.ConfigEntry + opDelete configentry.KindName expectErr string expectGraphErr bool } + + EMPTY_KN := configentry.KindName{} + + run := func(t *testing.T, tc tcase) { + s := testConfigStateStore(t) + for _, entry := range tc.entries { + require.NoError(t, ensureConfigEntry(s, 0, entry)) + } + + nOps := 0 + if tc.opAdd != nil { + nOps++ + } + if tc.opDelete != EMPTY_KN { + nOps++ + } + require.Equal(t, 1, nOps, "exactly one operation is required") + + var err error + switch { + case tc.opAdd != nil: + err = ensureConfigEntry(s, 0, tc.opAdd) + case tc.opDelete != EMPTY_KN: + kn := tc.opDelete + err = s.DeleteConfigEntry(0, kn.Kind, kn.Name, &kn.EnterpriseMeta) + default: + t.Fatal("not possible") + } + + if tc.expectErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectErr) + _, ok := err.(*structs.ConfigEntryGraphError) + if tc.expectGraphErr { + require.True(t, ok, "%T is not a *ConfigEntryGraphError", err) + } else { + require.False(t, ok, "did not expect a *ConfigEntryGraphError here: %v", err) + } + } else { + require.NoError(t, err) + } + } + cases := map[string]tcase{ "splitter fails without default protocol": { entries: []structs.ConfigEntry{}, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceSplitterConfigEntry{ - Kind: structs.ServiceSplitter, - Name: "main", - Splits: []structs.ServiceSplit{ - {Weight: 100}, - }, - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceSplitterConfigEntry{ + Kind: structs.ServiceSplitter, + Name: "main", + Splits: []structs.ServiceSplit{ + {Weight: 100}, + }, }, expectErr: "does not permit advanced routing or splitting behavior", expectGraphErr: true, @@ -873,15 +924,12 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { Protocol: "tcp", }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceSplitterConfigEntry{ - Kind: structs.ServiceSplitter, - Name: "main", - Splits: []structs.ServiceSplit{ - {Weight: 100}, - }, - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceSplitterConfigEntry{ + Kind: structs.ServiceSplitter, + Name: "main", + Splits: []structs.ServiceSplit{ + {Weight: 100}, + }, }, expectErr: "does not permit advanced routing or splitting behavior", expectGraphErr: true, @@ -914,17 +962,14 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceSplitterConfigEntry{ - Kind: structs.ServiceSplitter, - Name: "main", - Splits: []structs.ServiceSplit{ - {Weight: 90, ServiceSubset: "v1"}, - {Weight: 10, ServiceSubset: "v2"}, - }, - EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(), - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceSplitterConfigEntry{ + Kind: structs.ServiceSplitter, + Name: "main", + Splits: []structs.ServiceSplit{ + {Weight: 90, ServiceSubset: "v1"}, + {Weight: 10, ServiceSubset: "v2"}, + }, + EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(), }, }, "splitter works with http protocol (from proxy-defaults)": { @@ -949,16 +994,13 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceSplitterConfigEntry{ - Kind: structs.ServiceSplitter, - Name: "main", - Splits: []structs.ServiceSplit{ - {Weight: 90, ServiceSubset: "v1"}, - {Weight: 10, ServiceSubset: "v2"}, - }, - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceSplitterConfigEntry{ + Kind: structs.ServiceSplitter, + Name: "main", + Splits: []structs.ServiceSplit{ + {Weight: 90, ServiceSubset: "v1"}, + {Weight: 10, ServiceSubset: "v2"}, + }, }, }, "router fails with tcp protocol": { @@ -978,24 +1020,21 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceRouterConfigEntry{ - Kind: structs.ServiceRouter, - Name: "main", - Routes: []structs.ServiceRoute{ - { - Match: &structs.ServiceRouteMatch{ - HTTP: &structs.ServiceRouteHTTPMatch{ - PathExact: "/other", - }, - }, - Destination: &structs.ServiceRouteDestination{ - ServiceSubset: "other", + opAdd: &structs.ServiceRouterConfigEntry{ + Kind: structs.ServiceRouter, + Name: "main", + Routes: []structs.ServiceRoute{ + { + Match: &structs.ServiceRouteMatch{ + HTTP: &structs.ServiceRouteHTTPMatch{ + PathExact: "/other", }, }, + Destination: &structs.ServiceRouteDestination{ + ServiceSubset: "other", + }, }, - } - return s.EnsureConfigEntry(0, entry) + }, }, expectErr: "does not permit advanced routing or splitting behavior", expectGraphErr: true, @@ -1012,24 +1051,21 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceRouterConfigEntry{ - Kind: structs.ServiceRouter, - Name: "main", - Routes: []structs.ServiceRoute{ - { - Match: &structs.ServiceRouteMatch{ - HTTP: &structs.ServiceRouteHTTPMatch{ - PathExact: "/other", - }, - }, - Destination: &structs.ServiceRouteDestination{ - ServiceSubset: "other", + opAdd: &structs.ServiceRouterConfigEntry{ + Kind: structs.ServiceRouter, + Name: "main", + Routes: []structs.ServiceRoute{ + { + Match: &structs.ServiceRouteMatch{ + HTTP: &structs.ServiceRouteHTTPMatch{ + PathExact: "/other", }, }, + Destination: &structs.ServiceRouteDestination{ + ServiceSubset: "other", + }, }, - } - return s.EnsureConfigEntry(0, entry) + }, }, expectErr: "does not permit advanced routing or splitting behavior", expectGraphErr: true, @@ -1063,9 +1099,7 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - return s.DeleteConfigEntry(0, structs.ServiceDefaults, "main", nil) - }, + opDelete: configentry.NewKindName(structs.ServiceDefaults, "main", nil), expectErr: "does not permit advanced routing or splitting behavior", expectGraphErr: true, }, @@ -1099,9 +1133,7 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - return s.DeleteConfigEntry(0, structs.ProxyDefaults, structs.ProxyConfigGlobal, nil) - }, + opDelete: configentry.NewKindName(structs.ProxyDefaults, structs.ProxyConfigGlobal, nil), expectErr: "does not permit advanced routing or splitting behavior", expectGraphErr: true, }, @@ -1140,9 +1172,7 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - return s.DeleteConfigEntry(0, structs.ProxyDefaults, structs.ProxyConfigGlobal, nil) - }, + opDelete: configentry.NewKindName(structs.ProxyDefaults, structs.ProxyConfigGlobal, nil), }, "cannot change to tcp protocol after splitter created": { entries: []structs.ConfigEntry{ @@ -1172,13 +1202,10 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceConfigEntry{ - Kind: structs.ServiceDefaults, - Name: "main", - Protocol: "tcp", - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceConfigEntry{ + Kind: structs.ServiceDefaults, + Name: "main", + Protocol: "tcp", }, expectErr: "does not permit advanced routing or splitting behavior", expectGraphErr: true, @@ -1216,9 +1243,7 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - return s.DeleteConfigEntry(0, structs.ServiceDefaults, "main", nil) - }, + opDelete: configentry.NewKindName(structs.ServiceDefaults, "main", nil), expectErr: "does not permit advanced routing or splitting behavior", expectGraphErr: true, }, @@ -1255,13 +1280,10 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceConfigEntry{ - Kind: structs.ServiceDefaults, - Name: "main", - Protocol: "tcp", - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceConfigEntry{ + Kind: structs.ServiceDefaults, + Name: "main", + Protocol: "tcp", }, expectErr: "does not permit advanced routing or splitting behavior", expectGraphErr: true, @@ -1280,16 +1302,13 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { Protocol: "tcp", }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceSplitterConfigEntry{ - Kind: structs.ServiceSplitter, - Name: "main", - Splits: []structs.ServiceSplit{ - {Weight: 90}, - {Weight: 10, Service: "other"}, - }, - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceSplitterConfigEntry{ + Kind: structs.ServiceSplitter, + Name: "main", + Splits: []structs.ServiceSplit{ + {Weight: 90}, + {Weight: 10, Service: "other"}, + }, }, expectErr: "uses inconsistent protocols", expectGraphErr: true, @@ -1307,24 +1326,21 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { Protocol: "tcp", }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceRouterConfigEntry{ - Kind: structs.ServiceRouter, - Name: "main", - Routes: []structs.ServiceRoute{ - { - Match: &structs.ServiceRouteMatch{ - HTTP: &structs.ServiceRouteHTTPMatch{ - PathExact: "/other", - }, - }, - Destination: &structs.ServiceRouteDestination{ - Service: "other", + opAdd: &structs.ServiceRouterConfigEntry{ + Kind: structs.ServiceRouter, + Name: "main", + Routes: []structs.ServiceRoute{ + { + Match: &structs.ServiceRouteMatch{ + HTTP: &structs.ServiceRouteHTTPMatch{ + PathExact: "/other", }, }, + Destination: &structs.ServiceRouteDestination{ + Service: "other", + }, }, - } - return s.EnsureConfigEntry(0, entry) + }, }, expectErr: "uses inconsistent protocols", expectGraphErr: true, @@ -1348,17 +1364,14 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { ConnectTimeout: 33 * time.Second, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "main", - Failover: map[string]structs.ServiceResolverFailover{ - "*": { - Service: "other", - }, + opAdd: &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "main", + Failover: map[string]structs.ServiceResolverFailover{ + "*": { + Service: "other", }, - } - return s.EnsureConfigEntry(0, entry) + }, }, expectErr: "uses inconsistent protocols", expectGraphErr: true, @@ -1381,15 +1394,12 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { ConnectTimeout: 33 * time.Second, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "main", - Redirect: &structs.ServiceResolverRedirect{ - Service: "other", - }, - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "main", + Redirect: &structs.ServiceResolverRedirect{ + Service: "other", + }, }, expectErr: "uses inconsistent protocols", expectGraphErr: true, @@ -1408,16 +1418,13 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "main", - Redirect: &structs.ServiceResolverRedirect{ - Service: "other", - ServiceSubset: "v1", - }, - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "main", + Redirect: &structs.ServiceResolverRedirect{ + Service: "other", + ServiceSubset: "v1", + }, }, }, "cannot redirect to a subset that does not exist": { @@ -1428,16 +1435,13 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { ConnectTimeout: 33 * time.Second, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "main", - Redirect: &structs.ServiceResolverRedirect{ - Service: "other", - ServiceSubset: "v1", - }, - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "main", + Redirect: &structs.ServiceResolverRedirect{ + Service: "other", + ServiceSubset: "v1", + }, }, expectErr: `does not have a subset named "v1"`, expectGraphErr: true, @@ -1453,15 +1457,12 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceResolverConfigEntry{ - Kind: structs.ServiceResolver, - Name: "main", - Redirect: &structs.ServiceResolverRedirect{ - Service: "other", - }, - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "main", + Redirect: &structs.ServiceResolverRedirect{ + Service: "other", + }, }, expectErr: `detected circular resolver redirect`, expectGraphErr: true, @@ -1483,45 +1484,121 @@ func TestStore_ConfigEntry_GraphValidation(t *testing.T) { }, }, }, - op: func(t *testing.T, s *Store) error { - entry := &structs.ServiceSplitterConfigEntry{ - Kind: "service-splitter", - Name: "main", - Splits: []structs.ServiceSplit{ - {Weight: 100, Service: "other"}, - }, - } - return s.EnsureConfigEntry(0, entry) + opAdd: &structs.ServiceSplitterConfigEntry{ + Kind: "service-splitter", + Name: "main", + Splits: []structs.ServiceSplit{ + {Weight: 100, Service: "other"}, + }, }, expectErr: `detected circular reference`, expectGraphErr: true, }, + ///////////////////////////////////////////////// + "cannot peer export cross-dc redirect": { + entries: []structs.ConfigEntry{ + &structs.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + Redirect: &structs.ServiceResolverRedirect{ + Datacenter: "dc3", + }, + }, + }, + opAdd: &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{{ + Name: "main", + Consumers: []structs.ServiceConsumer{{PeerName: "my-peer"}}, + }}, + }, + expectErr: `contains cross-datacenter resolver redirect`, + }, + "cannot peer export cross-dc redirect via wildcard": { + entries: []structs.ConfigEntry{ + &structs.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + Redirect: &structs.ServiceResolverRedirect{ + Datacenter: "dc3", + }, + }, + }, + opAdd: &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{{ + Name: "*", + Consumers: []structs.ServiceConsumer{{PeerName: "my-peer"}}, + }}, + }, + expectErr: `contains cross-datacenter resolver redirect`, + }, + "cannot peer export cross-dc failover": { + entries: []structs.ConfigEntry{ + &structs.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + Failover: map[string]structs.ServiceResolverFailover{ + "*": { + Datacenters: []string{"dc3"}, + }, + }, + }, + }, + opAdd: &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{{ + Name: "main", + Consumers: []structs.ServiceConsumer{{PeerName: "my-peer"}}, + }}, + }, + expectErr: `contains cross-datacenter failover`, + }, + "cannot peer export cross-dc failover via wildcard": { + entries: []structs.ConfigEntry{ + &structs.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + Failover: map[string]structs.ServiceResolverFailover{ + "*": { + Datacenters: []string{"dc3"}, + }, + }, + }, + }, + opAdd: &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{{ + Name: "*", + Consumers: []structs.ServiceConsumer{{PeerName: "my-peer"}}, + }}, + }, + expectErr: `contains cross-datacenter failover`, + }, + "cannot redirect a peer exported tcp service": { + entries: []structs.ConfigEntry{ + &structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{{ + Name: "main", + Consumers: []structs.ServiceConsumer{{PeerName: "my-peer"}}, + }}, + }, + }, + opAdd: &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "main", + Redirect: &structs.ServiceResolverRedirect{ + Service: "other", + }, + }, + expectErr: `cannot introduce new discovery chain targets like`, + }, } for name, tc := range cases { - name := name - tc := tc - t.Run(name, func(t *testing.T) { - s := testConfigStateStore(t) - for _, entry := range tc.entries { - require.NoError(t, entry.Normalize()) - require.NoError(t, s.EnsureConfigEntry(0, entry)) - } - - err := tc.op(t, s) - if tc.expectErr != "" { - require.Error(t, err) - require.Contains(t, err.Error(), tc.expectErr) - _, ok := err.(*structs.ConfigEntryGraphError) - if tc.expectGraphErr { - require.True(t, ok, "%T is not a *ConfigEntryGraphError", err) - } else { - require.False(t, ok, "did not expect a *ConfigEntryGraphError here: %v", err) - } - } else { - require.NoError(t, err) - } + run(t, tc) }) } } diff --git a/agent/consul/state/peering.go b/agent/consul/state/peering.go index af5098987c..e486849231 100644 --- a/agent/consul/state/peering.go +++ b/agent/consul/state/peering.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/go-memdb" "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/configentry" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/lib/maps" "github.com/hashicorp/consul/proto/pbpeering" @@ -154,10 +155,10 @@ func peeringReadTxn(tx ReadTxn, ws memdb.WatchSet, q Query) (uint64, *pbpeering. func (s *Store) PeeringList(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.Peering, error) { tx := s.db.ReadTxn() defer tx.Abort() - return s.peeringListTxn(ws, tx, entMeta) + return peeringListTxn(ws, tx, entMeta) } -func (s *Store) peeringListTxn(ws memdb.WatchSet, tx ReadTxn, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.Peering, error) { +func peeringListTxn(ws memdb.WatchSet, tx ReadTxn, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.Peering, error) { var ( iter memdb.ResultIterator err error @@ -322,21 +323,21 @@ func (s *Store) ExportedServicesForPeer(ws memdb.WatchSet, peerID string, dc str return 0, &structs.ExportedServiceList{}, nil } - return s.exportedServicesForPeerTxn(ws, tx, peering, dc) + return exportedServicesForPeerTxn(ws, tx, peering, dc) } func (s *Store) ExportedServicesForAllPeersByName(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, map[string]structs.ServiceList, error) { tx := s.db.ReadTxn() defer tx.Abort() - maxIdx, peerings, err := s.peeringListTxn(ws, tx, entMeta) + maxIdx, peerings, err := peeringListTxn(ws, tx, entMeta) if err != nil { return 0, nil, fmt.Errorf("failed to list peerings: %w", err) } out := make(map[string]structs.ServiceList) for _, peering := range peerings { - idx, list, err := s.exportedServicesForPeerTxn(ws, tx, peering, "") + idx, list, err := exportedServicesForPeerTxn(ws, tx, peering, "") if err != nil { return 0, nil, fmt.Errorf("failed to list exported services for peer %q: %w", peering.ID, err) } @@ -356,34 +357,31 @@ func (s *Store) ExportedServicesForAllPeersByName(ws memdb.WatchSet, entMeta acl // specific peering, and optionally include information about discovery chain // reachable targets for these exported services if the "dc" parameter is // specified. -func (s *Store) exportedServicesForPeerTxn(ws memdb.WatchSet, tx ReadTxn, peering *pbpeering.Peering, dc string) (uint64, *structs.ExportedServiceList, error) { +func exportedServicesForPeerTxn( + ws memdb.WatchSet, + tx ReadTxn, + peering *pbpeering.Peering, + dc string, +) (uint64, *structs.ExportedServiceList, error) { maxIdx := peering.ModifyIndex entMeta := structs.NodeEnterpriseMetaInPartition(peering.Partition) - idx, raw, err := configEntryTxn(tx, ws, structs.ExportedServices, entMeta.PartitionOrDefault(), entMeta) + idx, conf, err := getExportedServicesConfigEntryTxn(tx, ws, nil, entMeta) if err != nil { return 0, nil, fmt.Errorf("failed to fetch exported-services config entry: %w", err) } if idx > maxIdx { maxIdx = idx } - if raw == nil { + if conf == nil { return maxIdx, &structs.ExportedServiceList{}, nil } - conf, ok := raw.(*structs.ExportedServicesConfigEntry) - if !ok { - return 0, nil, fmt.Errorf("expected type *structs.ExportedServicesConfigEntry, got %T", raw) - } - var ( normalSet = make(map[structs.ServiceName]struct{}) discoSet = make(map[structs.ServiceName]struct{}) ) - // TODO(peering): filter the disco chain portion of the results to only be - // things reachable over the mesh to avoid replicating some clutter. - // // At least one of the following should be true for a name for it to // replicate: // @@ -426,7 +424,7 @@ func (s *Store) exportedServicesForPeerTxn(ws memdb.WatchSet, tx ReadTxn, peerin } // list all config entries of kind service-resolver, service-router, service-splitter? - idx, discoChains, err := listDiscoveryChainNamesTxn(tx, ws, svcMeta) + idx, discoChains, err := listDiscoveryChainNamesTxn(tx, ws, nil, svcMeta) if err != nil { return 0, nil, fmt.Errorf("failed to get discovery chain names: %w", err) } @@ -463,7 +461,7 @@ func (s *Store) exportedServicesForPeerTxn(ws memdb.WatchSet, tx ReadTxn, peerin if dc != "" && !structs.IsProtocolHTTPLike(protocol) { // We only need to populate the targets for replication purposes for L4 protocols, which // do not ultimately get intercepted by the mesh gateways. - idx, targets, err := s.discoveryChainOriginalTargetsTxn(tx, ws, dc, svc.Name, &svc.EnterpriseMeta) + idx, targets, err := discoveryChainOriginalTargetsTxn(tx, ws, dc, svc.Name, &svc.EnterpriseMeta) if err != nil { return fmt.Errorf("failed to get discovery chain targets for service %q: %w", svc, err) } @@ -504,6 +502,86 @@ func (s *Store) exportedServicesForPeerTxn(ws memdb.WatchSet, tx ReadTxn, peerin return maxIdx, list, nil } +func listAllExportedServices( + ws memdb.WatchSet, + tx ReadTxn, + overrides map[configentry.KindName]structs.ConfigEntry, + entMeta acl.EnterpriseMeta, +) (uint64, map[structs.ServiceName]struct{}, error) { + idx, export, err := getExportedServicesConfigEntryTxn(tx, ws, overrides, &entMeta) + if err != nil { + return 0, nil, err + } + + found := make(map[structs.ServiceName]struct{}) + if export == nil { + return idx, found, nil + } + + _, services, err := listServicesExportedToAnyPeerByConfigEntry(ws, tx, export, overrides) + if err != nil { + return 0, nil, err + } + for _, svc := range services { + found[svc] = struct{}{} + } + + return idx, found, nil +} + +func listServicesExportedToAnyPeerByConfigEntry( + ws memdb.WatchSet, + tx ReadTxn, + conf *structs.ExportedServicesConfigEntry, + overrides map[configentry.KindName]structs.ConfigEntry, +) (uint64, []structs.ServiceName, error) { + var ( + entMeta = conf.GetEnterpriseMeta() + found = make(map[structs.ServiceName]struct{}) + maxIdx uint64 + ) + + for _, svc := range conf.Services { + svcMeta := acl.NewEnterpriseMetaWithPartition(entMeta.PartitionOrDefault(), svc.Namespace) + + sawPeer := false + for _, consumer := range svc.Consumers { + if consumer.PeerName == "" { + continue + } + sawPeer = true + + sn := structs.NewServiceName(svc.Name, &svcMeta) + if _, ok := found[sn]; ok { + continue + } + + if svc.Name != structs.WildcardSpecifier { + found[sn] = struct{}{} + } + } + + if sawPeer && svc.Name == structs.WildcardSpecifier { + idx, discoChains, err := listDiscoveryChainNamesTxn(tx, ws, overrides, svcMeta) + if err != nil { + return 0, nil, fmt.Errorf("failed to get discovery chain names: %w", err) + } + if idx > maxIdx { + maxIdx = idx + } + for _, sn := range discoChains { + found[sn] = struct{}{} + } + } + } + + foundKeys := maps.SliceOfKeys(found) + + structs.ServiceList(foundKeys).Sort() + + return maxIdx, foundKeys, nil +} + // PeeringsForService returns the list of peerings that are associated with the service name provided in the query. // This is used to configure connect proxies for a given service. The result is generated by querying for exported // service config entries and filtering for those that match the given service. diff --git a/agent/consul/subscribe_backend.go b/agent/consul/subscribe_backend.go index bddbb2e5fa..a82bb98c0b 100644 --- a/agent/consul/subscribe_backend.go +++ b/agent/consul/subscribe_backend.go @@ -5,7 +5,7 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/stream" - "github.com/hashicorp/consul/agent/grpc/private/services/subscribe" + "github.com/hashicorp/consul/agent/grpc-internal/services/subscribe" "github.com/hashicorp/consul/agent/structs" ) diff --git a/agent/consul/subscribe_backend_test.go b/agent/consul/subscribe_backend_test.go index a6ac36ca23..b7ea7e2d3b 100644 --- a/agent/consul/subscribe_backend_test.go +++ b/agent/consul/subscribe_backend_test.go @@ -14,8 +14,8 @@ import ( "golang.org/x/sync/errgroup" gogrpc "google.golang.org/grpc" - grpc "github.com/hashicorp/consul/agent/grpc/private" - "github.com/hashicorp/consul/agent/grpc/private/resolver" + grpc "github.com/hashicorp/consul/agent/grpc-internal" + "github.com/hashicorp/consul/agent/grpc-internal/resolver" "github.com/hashicorp/consul/agent/router" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/pbservice" diff --git a/agent/dns.go b/agent/dns.go index 9d0d3b9a5b..b627f1f4a8 100644 --- a/agent/dns.go +++ b/agent/dns.go @@ -676,15 +676,34 @@ func (e ecsNotGlobalError) Unwrap() error { return e.error } +type queryLocality struct { + // datacenter is the datacenter parsed from a label that has an explicit datacenter part. + // Example query: .virtual..ns..ap..dc.consul + datacenter string + + // peerOrDatacenter is parsed from DNS queries where the datacenter and peer name are specified in the same query part. + // Example query: .virtual..consul + peerOrDatacenter string + + acl.EnterpriseMeta +} + +func (l queryLocality) effectiveDatacenter(defaultDC string) string { + // Prefer the value parsed from a query with explicit parts: .ns..ap..dc + if l.datacenter != "" { + return l.datacenter + } + // Fall back to the ambiguously parsed DC or Peer. + if l.peerOrDatacenter != "" { + return l.peerOrDatacenter + } + // If all are empty, use a default value. + return defaultDC +} + // dispatch is used to parse a request and invoke the correct handler. // parameter maxRecursionLevel will handle whether recursive call can be performed func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursionLevel int) error { - // By default the query is in the default datacenter - datacenter := d.agent.config.Datacenter - - // have to deref to clone it so we don't modify (start from the agent's defaults) - var entMeta = d.defaultEnterpriseMeta - // Choose correct response domain respDomain := d.getResponseDomain(req.Question[0].Name) @@ -733,16 +752,17 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi return invalid() } - if !d.parseDatacenterAndEnterpriseMeta(querySuffixes, cfg, &datacenter, &entMeta) { + locality, ok := d.parseLocality(querySuffixes, cfg) + if !ok { return invalid() } lookup := serviceLookup{ - Datacenter: datacenter, + Datacenter: locality.effectiveDatacenter(d.agent.config.Datacenter), Connect: false, Ingress: false, MaxRecursionLevel: maxRecursionLevel, - EnterpriseMeta: entMeta, + EnterpriseMeta: locality.EnterpriseMeta, } // Support RFC 2782 style syntax if n == 2 && strings.HasPrefix(queryParts[1], "_") && strings.HasPrefix(queryParts[0], "_") { @@ -779,17 +799,18 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi return invalid() } - if !d.parseDatacenterAndEnterpriseMeta(querySuffixes, cfg, &datacenter, &entMeta) { + locality, ok := d.parseLocality(querySuffixes, cfg) + if !ok { return invalid() } lookup := serviceLookup{ - Datacenter: datacenter, + Datacenter: locality.effectiveDatacenter(d.agent.config.Datacenter), Service: queryParts[len(queryParts)-1], Connect: true, Ingress: false, MaxRecursionLevel: maxRecursionLevel, - EnterpriseMeta: entMeta, + EnterpriseMeta: locality.EnterpriseMeta, } // name.connect.consul return d.serviceLookup(cfg, lookup, req, resp) @@ -799,14 +820,18 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi return invalid() } - if !d.parseDatacenterAndEnterpriseMeta(querySuffixes, cfg, &datacenter, &entMeta) { + locality, ok := d.parseLocality(querySuffixes, cfg) + if !ok { return invalid() } args := structs.ServiceSpecificRequest{ - Datacenter: datacenter, + // The datacenter of the request is not specified because cross-datacenter virtual IP + // queries are not supported. This guard rail is in place because virtual IPs are allocated + // within a DC, therefore their uniqueness is not guaranteed globally. + PeerName: locality.peerOrDatacenter, ServiceName: queryParts[len(queryParts)-1], - EnterpriseMeta: entMeta, + EnterpriseMeta: locality.EnterpriseMeta, QueryOptions: structs.QueryOptions{ Token: d.agent.tokens.UserToken(), }, @@ -834,17 +859,18 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi return invalid() } - if !d.parseDatacenterAndEnterpriseMeta(querySuffixes, cfg, &datacenter, &entMeta) { + locality, ok := d.parseLocality(querySuffixes, cfg) + if !ok { return invalid() } lookup := serviceLookup{ - Datacenter: datacenter, + Datacenter: locality.effectiveDatacenter(d.agent.config.Datacenter), Service: queryParts[len(queryParts)-1], Connect: false, Ingress: true, MaxRecursionLevel: maxRecursionLevel, - EnterpriseMeta: entMeta, + EnterpriseMeta: locality.EnterpriseMeta, } // name.ingress.consul return d.serviceLookup(cfg, lookup, req, resp) @@ -854,13 +880,14 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi return invalid() } - if !d.parseDatacenterAndEnterpriseMeta(querySuffixes, cfg, &datacenter, &entMeta) { + locality, ok := d.parseLocality(querySuffixes, cfg) + if !ok { return invalid() } - // Namespace should not be set for node queries - ns := entMeta.NamespaceOrEmpty() - if ns != "" && ns != acl.DefaultNamespaceName { + // Nodes are only registered in the default namespace so queries + // must not specify a non-default namespace. + if !locality.InDefaultNamespace() { return invalid() } @@ -868,15 +895,17 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi node := strings.Join(queryParts, ".") lookup := nodeLookup{ - Datacenter: datacenter, + Datacenter: locality.effectiveDatacenter(d.agent.config.Datacenter), Node: node, MaxRecursionLevel: maxRecursionLevel, - EnterpriseMeta: entMeta, + EnterpriseMeta: locality.EnterpriseMeta, } return d.nodeLookup(cfg, lookup, req, resp) case "query": + datacenter := d.agent.config.Datacenter + // ensure we have a query name if len(queryParts) < 1 { return invalid() @@ -905,7 +934,7 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi if err != nil { return invalid() } - //check if the query type is A for IPv4 or ANY + // check if the query type is A for IPv4 or ANY aRecord := &dns.A{ Hdr: dns.RR_Header{ Name: qName + respDomain, @@ -926,7 +955,7 @@ func (d *DNSServer) dispatch(remoteAddr net.Addr, req, resp *dns.Msg, maxRecursi if err != nil { return invalid() } - //check if the query type is AAAA for IPv6 or ANY + // check if the query type is AAAA for IPv6 or ANY aaaaRecord := &dns.AAAA{ Hdr: dns.RR_Header{ Name: qName + respDomain, diff --git a/agent/dns_oss.go b/agent/dns_oss.go index 9476e810f1..de257aa4cc 100644 --- a/agent/dns_oss.go +++ b/agent/dns_oss.go @@ -16,15 +16,19 @@ func getEnterpriseDNSConfig(conf *config.RuntimeConfig) enterpriseDNSConfig { return enterpriseDNSConfig{} } -func (d *DNSServer) parseDatacenterAndEnterpriseMeta(labels []string, _ *dnsConfig, datacenter *string, _ *acl.EnterpriseMeta) bool { +// parseLocality can parse peer name or datacenter from a DNS query's labels. +// Peer name is parsed from the same query part that datacenter is, so given this ambiguity +// we parse a "peerOrDatacenter". The caller or RPC handler are responsible for disambiguating. +func (d *DNSServer) parseLocality(labels []string, cfg *dnsConfig) (queryLocality, bool) { switch len(labels) { case 1: - *datacenter = labels[0] - return true + return queryLocality{peerOrDatacenter: labels[0]}, true + case 0: - return true + return queryLocality{}, true } - return false + + return queryLocality{}, false } func serviceCanonicalDNSName(name, kind, datacenter, domain string, _ *acl.EnterpriseMeta) string { diff --git a/agent/dns_test.go b/agent/dns_test.go index 6d4085833e..f0d82d2e77 100644 --- a/agent/dns_test.go +++ b/agent/dns_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/serf/coordinate" "github.com/miekg/dns" "github.com/stretchr/testify/require" @@ -458,7 +459,7 @@ func TestDNSCycleRecursorCheck(t *testing.T) { }, }) defer server2.Shutdown() - //Mock the agent startup with the necessary configs + // Mock the agent startup with the necessary configs agent := NewTestAgent(t, `recursors = ["`+server1.Addr+`", "`+server2.Addr+`"] `) @@ -496,7 +497,7 @@ func TestDNSCycleRecursorCheckAllFail(t *testing.T) { MsgHdr: dns.MsgHdr{Rcode: dns.RcodeRefused}, }) defer server3.Shutdown() - //Mock the agent startup with the necessary configs + // Mock the agent startup with the necessary configs agent := NewTestAgent(t, `recursors = ["`+server1.Addr+`", "`+server2.Addr+`","`+server3.Addr+`"] `) @@ -507,7 +508,7 @@ func TestDNSCycleRecursorCheckAllFail(t *testing.T) { // Agent request client := new(dns.Client) in, _, _ := client.Exchange(m, agent.DNSAddr()) - //Verify if we hit SERVFAIL from Consul + // Verify if we hit SERVFAIL from Consul require.Equal(t, dns.RcodeServerFailure, in.Rcode) } func TestDNS_NodeLookup_CNAME(t *testing.T) { @@ -1756,14 +1757,42 @@ func TestDNS_ConnectServiceLookup(t *testing.T) { require.Equal(t, uint32(0), srvRec.Hdr.Ttl) require.Equal(t, "127.0.0.55", cnameRec.A.String()) } +} - // Look up the virtual IP of the proxy. - questions = []string{ - "db.virtual.consul.", +func TestDNS_VirtualIPLookup(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") } - for _, question := range questions { + + t.Parallel() + + a := NewTestAgent(t, "") + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + server, ok := a.delegate.(*consul.Server) + require.True(t, ok) + + // The proxy service will not receive a virtual IP if the server is not assigning virtual IPs yet. + retry.Run(t, func(r *retry.R) { + _, entry, err := server.FSM().State().SystemMetadataGet(nil, structs.SystemMetadataVirtualIPsEnabled) + require.NoError(r, err) + require.NotNil(r, entry) + }) + + type testCase struct { + name string + reg *structs.RegisterRequest + question string + expect string + } + + run := func(t *testing.T, tc testCase) { + var out struct{} + require.Nil(t, a.RPC("Catalog.Register", tc.reg, &out)) + m := new(dns.Msg) - m.SetQuestion(question, dns.TypeA) + m.SetQuestion(tc.question, dns.TypeA) c := new(dns.Client) in, _, err := c.Exchange(m, a.DNSAddr()) @@ -1772,7 +1801,54 @@ func TestDNS_ConnectServiceLookup(t *testing.T) { aRec, ok := in.Answer[0].(*dns.A) require.True(t, ok) - require.Equal(t, "240.0.0.1", aRec.A.String()) + require.Equal(t, tc.expect, aRec.A.String()) + } + + tt := []testCase{ + { + name: "local query", + reg: &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.55", + Service: &structs.NodeService{ + Kind: structs.ServiceKindConnectProxy, + Service: "web-proxy", + Port: 12345, + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "db", + }, + }, + }, + question: "db.virtual.consul.", + expect: "240.0.0.1", + }, + { + name: "query for imported service", + reg: &structs.RegisterRequest{ + PeerName: "frontend", + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.55", + Service: &structs.NodeService{ + PeerName: "frontend", + Kind: structs.ServiceKindConnectProxy, + Service: "web-proxy", + Port: 12345, + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "db", + }, + }, + }, + question: "db.virtual.frontend.consul.", + expect: "240.0.0.2", + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + run(t, tc) + }) } } diff --git a/agent/grpc/public/forward.go b/agent/grpc-external/forward.go similarity index 93% rename from agent/grpc/public/forward.go rename to agent/grpc-external/forward.go index 398d33d516..353490a593 100644 --- a/agent/grpc/public/forward.go +++ b/agent/grpc-external/forward.go @@ -1,4 +1,4 @@ -package public +package external import ( "context" diff --git a/agent/grpc/public/server.go b/agent/grpc-external/server.go similarity index 86% rename from agent/grpc/public/server.go rename to agent/grpc-external/server.go index c235fbd092..606dba642b 100644 --- a/agent/grpc/public/server.go +++ b/agent/grpc-external/server.go @@ -1,4 +1,4 @@ -package public +package external import ( middleware "github.com/grpc-ecosystem/go-grpc-middleware" @@ -6,11 +6,11 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials" - agentmiddleware "github.com/hashicorp/consul/agent/grpc/middleware" + agentmiddleware "github.com/hashicorp/consul/agent/grpc-middleware" "github.com/hashicorp/consul/tlsutil" ) -// NewServer constructs a gRPC server for the public gRPC port, to which +// NewServer constructs a gRPC server for the external gRPC port, to which // handlers can be registered. func NewServer(logger agentmiddleware.Logger, tls *tlsutil.Configurator) *grpc.Server { recoveryOpts := agentmiddleware.PanicHandlerMiddlewareOpts(logger) diff --git a/agent/grpc/public/services/acl/login.go b/agent/grpc-external/services/acl/login.go similarity index 95% rename from agent/grpc/public/services/acl/login.go rename to agent/grpc-external/services/acl/login.go index 1a68b1eb2f..629ea093ec 100644 --- a/agent/grpc/public/services/acl/login.go +++ b/agent/grpc-external/services/acl/login.go @@ -10,14 +10,14 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/auth" - "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/proto-public/pbacl" ) // Login exchanges the presented bearer token for a Consul ACL token using a // configured auth method. func (s *Server) Login(ctx context.Context, req *pbacl.LoginRequest) (*pbacl.LoginResponse, error) { - logger := s.Logger.Named("login").With("request_id", public.TraceID()) + logger := s.Logger.Named("login").With("request_id", external.TraceID()) logger.Trace("request received") if err := s.requireACLsEnabled(logger); err != nil { diff --git a/agent/grpc/public/services/acl/login_test.go b/agent/grpc-external/services/acl/login_test.go similarity index 99% rename from agent/grpc/public/services/acl/login_test.go rename to agent/grpc-external/services/acl/login_test.go index 84b2693f43..3c681945f6 100644 --- a/agent/grpc/public/services/acl/login_test.go +++ b/agent/grpc-external/services/acl/login_test.go @@ -16,7 +16,7 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/authmethod" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + "github.com/hashicorp/consul/agent/grpc-external/testutils" structs "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbacl" ) diff --git a/agent/grpc/public/services/acl/logout.go b/agent/grpc-external/services/acl/logout.go similarity index 93% rename from agent/grpc/public/services/acl/logout.go rename to agent/grpc-external/services/acl/logout.go index 4f7fc3767a..a9fa60673b 100644 --- a/agent/grpc/public/services/acl/logout.go +++ b/agent/grpc-external/services/acl/logout.go @@ -10,13 +10,13 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/auth" - "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/proto-public/pbacl" ) // Logout destroys the given ACL token once the caller is done with it. func (s *Server) Logout(ctx context.Context, req *pbacl.LogoutRequest) (*pbacl.LogoutResponse, error) { - logger := s.Logger.Named("logout").With("request_id", public.TraceID()) + logger := s.Logger.Named("logout").With("request_id", external.TraceID()) logger.Trace("request received") if err := s.requireACLsEnabled(logger); err != nil { diff --git a/agent/grpc/public/services/acl/logout_test.go b/agent/grpc-external/services/acl/logout_test.go similarity index 99% rename from agent/grpc/public/services/acl/logout_test.go rename to agent/grpc-external/services/acl/logout_test.go index 461b6e249e..dfe998f319 100644 --- a/agent/grpc/public/services/acl/logout_test.go +++ b/agent/grpc-external/services/acl/logout_test.go @@ -15,7 +15,7 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/auth" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbacl" ) diff --git a/agent/grpc/public/services/acl/mock_Login.go b/agent/grpc-external/services/acl/mock_Login.go similarity index 100% rename from agent/grpc/public/services/acl/mock_Login.go rename to agent/grpc-external/services/acl/mock_Login.go diff --git a/agent/grpc/public/services/acl/mock_TokenWriter.go b/agent/grpc-external/services/acl/mock_TokenWriter.go similarity index 100% rename from agent/grpc/public/services/acl/mock_TokenWriter.go rename to agent/grpc-external/services/acl/mock_TokenWriter.go diff --git a/agent/grpc/public/services/acl/mock_Validator.go b/agent/grpc-external/services/acl/mock_Validator.go similarity index 100% rename from agent/grpc/public/services/acl/mock_Validator.go rename to agent/grpc-external/services/acl/mock_Validator.go diff --git a/agent/grpc/public/services/acl/server.go b/agent/grpc-external/services/acl/server.go similarity index 100% rename from agent/grpc/public/services/acl/server.go rename to agent/grpc-external/services/acl/server.go diff --git a/agent/grpc/public/services/acl/server_test.go b/agent/grpc-external/services/acl/server_test.go similarity index 100% rename from agent/grpc/public/services/acl/server_test.go rename to agent/grpc-external/services/acl/server_test.go diff --git a/agent/grpc/public/services/connectca/mock_ACLResolver.go b/agent/grpc-external/services/connectca/mock_ACLResolver.go similarity index 100% rename from agent/grpc/public/services/connectca/mock_ACLResolver.go rename to agent/grpc-external/services/connectca/mock_ACLResolver.go diff --git a/agent/grpc/public/services/connectca/mock_CAManager.go b/agent/grpc-external/services/connectca/mock_CAManager.go similarity index 100% rename from agent/grpc/public/services/connectca/mock_CAManager.go rename to agent/grpc-external/services/connectca/mock_CAManager.go diff --git a/agent/grpc/public/services/connectca/server.go b/agent/grpc-external/services/connectca/server.go similarity index 100% rename from agent/grpc/public/services/connectca/server.go rename to agent/grpc-external/services/connectca/server.go diff --git a/agent/grpc/public/services/connectca/server_test.go b/agent/grpc-external/services/connectca/server_test.go similarity index 95% rename from agent/grpc/public/services/connectca/server_test.go rename to agent/grpc-external/services/connectca/server_test.go index 2d58bccb7a..824883fbd6 100644 --- a/agent/grpc/public/services/connectca/server_test.go +++ b/agent/grpc-external/services/connectca/server_test.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + "github.com/hashicorp/consul/agent/grpc-external/testutils" structs "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbconnectca" ) diff --git a/agent/grpc/public/services/connectca/sign.go b/agent/grpc-external/services/connectca/sign.go similarity index 93% rename from agent/grpc/public/services/connectca/sign.go rename to agent/grpc-external/services/connectca/sign.go index b3ace6d3d0..edd48fe58e 100644 --- a/agent/grpc/public/services/connectca/sign.go +++ b/agent/grpc-external/services/connectca/sign.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbconnectca" ) @@ -22,10 +22,10 @@ func (s *Server) Sign(ctx context.Context, req *pbconnectca.SignRequest) (*pbcon return nil, err } - logger := s.Logger.Named("sign").With("request_id", public.TraceID()) + logger := s.Logger.Named("sign").With("request_id", external.TraceID()) logger.Trace("request received") - token := public.TokenFromContext(ctx) + token := external.TokenFromContext(ctx) if req.Csr == "" { return nil, status.Error(codes.InvalidArgument, "CSR is required") @@ -48,7 +48,7 @@ func (s *Server) Sign(ctx context.Context, req *pbconnectca.SignRequest) (*pbcon var rsp *pbconnectca.SignResponse handled, err := s.ForwardRPC(&rpcInfo, func(conn *grpc.ClientConn) error { logger.Trace("forwarding RPC") - ctx := public.ForwardMetadataContext(ctx) + ctx := external.ForwardMetadataContext(ctx) var err error rsp, err = pbconnectca.NewConnectCAServiceClient(conn).Sign(ctx, req) return err diff --git a/agent/grpc/public/services/connectca/sign_test.go b/agent/grpc-external/services/connectca/sign_test.go similarity index 99% rename from agent/grpc/public/services/connectca/sign_test.go rename to agent/grpc-external/services/connectca/sign_test.go index aa20458f89..6bba0c197e 100644 --- a/agent/grpc/public/services/connectca/sign_test.go +++ b/agent/grpc-external/services/connectca/sign_test.go @@ -16,7 +16,7 @@ import ( acl "github.com/hashicorp/consul/acl" resolver "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbconnectca" ) diff --git a/agent/grpc/public/services/connectca/watch_roots.go b/agent/grpc-external/services/connectca/watch_roots.go similarity index 96% rename from agent/grpc/public/services/connectca/watch_roots.go rename to agent/grpc-external/services/connectca/watch_roots.go index bf455ce278..9c61f8bdd3 100644 --- a/agent/grpc/public/services/connectca/watch_roots.go +++ b/agent/grpc-external/services/connectca/watch_roots.go @@ -15,7 +15,7 @@ import ( "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" - "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbconnectca" ) @@ -28,11 +28,11 @@ func (s *Server) WatchRoots(_ *pbconnectca.WatchRootsRequest, serverStream pbcon return err } - logger := s.Logger.Named("watch-roots").With("request_id", public.TraceID()) + logger := s.Logger.Named("watch-roots").With("request_id", external.TraceID()) logger.Trace("starting stream") defer logger.Trace("stream closed") - token := public.TokenFromContext(serverStream.Context()) + token := external.TokenFromContext(serverStream.Context()) // Serve the roots from an EventPublisher subscription. If the subscription is // closed due to an ACL change, we'll attempt to re-authorize and resume it to diff --git a/agent/grpc/public/services/connectca/watch_roots_test.go b/agent/grpc-external/services/connectca/watch_roots_test.go similarity index 95% rename from agent/grpc/public/services/connectca/watch_roots_test.go rename to agent/grpc-external/services/connectca/watch_roots_test.go index b65bc014bf..2491417bb9 100644 --- a/agent/grpc/public/services/connectca/watch_roots_test.go +++ b/agent/grpc-external/services/connectca/watch_roots_test.go @@ -17,8 +17,8 @@ import ( "github.com/hashicorp/consul/acl" resolver "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/connect" - "github.com/hashicorp/consul/agent/grpc/public" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + external "github.com/hashicorp/consul/agent/grpc-external" + "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbconnectca" "github.com/hashicorp/consul/sdk/testutil" @@ -56,7 +56,7 @@ func TestWatchRoots_Success(t *testing.T) { aclResolver.On("ResolveTokenAndDefaultMeta", testACLToken, mock.Anything, mock.Anything). Return(testutils.TestAuthorizerServiceWriteAny(t), nil) - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) server := NewServer(Config{ Publisher: publisher, @@ -104,7 +104,7 @@ func TestWatchRoots_InvalidACLToken(t *testing.T) { aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). Return(resolver.Result{}, acl.ErrNotFound) - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) server := NewServer(Config{ Publisher: publisher, @@ -142,7 +142,7 @@ func TestWatchRoots_ACLTokenInvalidated(t *testing.T) { aclResolver.On("ResolveTokenAndDefaultMeta", testACLToken, mock.Anything, mock.Anything). Return(testutils.TestAuthorizerServiceWriteAny(t), nil).Twice() - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) server := NewServer(Config{ Publisher: publisher, @@ -210,7 +210,7 @@ func TestWatchRoots_StateStoreAbandoned(t *testing.T) { aclResolver.On("ResolveTokenAndDefaultMeta", testACLToken, mock.Anything, mock.Anything). Return(testutils.TestAuthorizerServiceWriteAny(t), nil) - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) server := NewServer(Config{ Publisher: publisher, diff --git a/agent/grpc/public/services/dataplane/get_envoy_boostrap_params_test.go b/agent/grpc-external/services/dataplane/get_envoy_boostrap_params_test.go similarity index 95% rename from agent/grpc/public/services/dataplane/get_envoy_boostrap_params_test.go rename to agent/grpc-external/services/dataplane/get_envoy_boostrap_params_test.go index e3a9ce703c..c3b4fd1468 100644 --- a/agent/grpc/public/services/dataplane/get_envoy_boostrap_params_test.go +++ b/agent/grpc-external/services/dataplane/get_envoy_boostrap_params_test.go @@ -13,8 +13,8 @@ import ( acl "github.com/hashicorp/consul/acl" resolver "github.com/hashicorp/consul/acl/resolver" - "github.com/hashicorp/consul/agent/grpc/public" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + external "github.com/hashicorp/consul/agent/grpc-external" + "github.com/hashicorp/consul/agent/grpc-external/testutils" structs "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbdataplane" "github.com/hashicorp/consul/types" @@ -78,7 +78,7 @@ func TestGetEnvoyBootstrapParams_Success(t *testing.T) { aclResolver := &MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", testToken, mock.Anything, mock.Anything). Return(testutils.TestAuthorizerServiceRead(t, tc.registerReq.Service.ID), nil) - ctx := public.ContextWithToken(context.Background(), testToken) + ctx := external.ContextWithToken(context.Background(), testToken) server := NewServer(Config{ GetStore: func() StateStore { return store }, @@ -148,7 +148,7 @@ func TestGetEnvoyBootstrapParams_Error(t *testing.T) { aclResolver.On("ResolveTokenAndDefaultMeta", testToken, mock.Anything, mock.Anything). Return(testutils.TestAuthorizerServiceRead(t, proxyServiceID), nil) - ctx := public.ContextWithToken(context.Background(), testToken) + ctx := external.ContextWithToken(context.Background(), testToken) store := testutils.TestStateStore(t, nil) registerReq := testRegisterRequestProxy(t) @@ -218,7 +218,7 @@ func TestGetEnvoyBootstrapParams_Unauthenticated(t *testing.T) { aclResolver := &MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). Return(resolver.Result{}, acl.ErrNotFound) - ctx := public.ContextWithToken(context.Background(), testToken) + ctx := external.ContextWithToken(context.Background(), testToken) store := testutils.TestStateStore(t, nil) server := NewServer(Config{ GetStore: func() StateStore { return store }, @@ -237,7 +237,7 @@ func TestGetEnvoyBootstrapParams_PermissionDenied(t *testing.T) { aclResolver := &MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", testToken, mock.Anything, mock.Anything). Return(testutils.TestAuthorizerDenyAll(t), nil) - ctx := public.ContextWithToken(context.Background(), testToken) + ctx := external.ContextWithToken(context.Background(), testToken) store := testutils.TestStateStore(t, nil) registerReq := structs.TestRegisterRequestProxy(t) proxyServiceID := "web-sidecar-proxy" diff --git a/agent/grpc/public/services/dataplane/get_envoy_bootstrap_params.go b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go similarity index 94% rename from agent/grpc/public/services/dataplane/get_envoy_bootstrap_params.go rename to agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go index 1b534672c5..bed302d12b 100644 --- a/agent/grpc/public/services/dataplane/get_envoy_bootstrap_params.go +++ b/agent/grpc-external/services/dataplane/get_envoy_bootstrap_params.go @@ -11,18 +11,18 @@ import ( acl "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/state" - "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" structs "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbdataplane" ) func (s *Server) GetEnvoyBootstrapParams(ctx context.Context, req *pbdataplane.GetEnvoyBootstrapParamsRequest) (*pbdataplane.GetEnvoyBootstrapParamsResponse, error) { - logger := s.Logger.Named("get-envoy-bootstrap-params").With("service_id", req.GetServiceId(), "request_id", public.TraceID()) + logger := s.Logger.Named("get-envoy-bootstrap-params").With("service_id", req.GetServiceId(), "request_id", external.TraceID()) logger.Trace("Started processing request") defer logger.Trace("Finished processing request") - token := public.TokenFromContext(ctx) + token := external.TokenFromContext(ctx) var authzContext acl.AuthorizerContext entMeta := acl.NewEnterpriseMetaWithPartition(req.GetPartition(), req.GetNamespace()) authz, err := s.ACLResolver.ResolveTokenAndDefaultMeta(token, &entMeta, &authzContext) diff --git a/agent/grpc/public/services/dataplane/get_supported_features.go b/agent/grpc-external/services/dataplane/get_supported_features.go similarity index 92% rename from agent/grpc/public/services/dataplane/get_supported_features.go rename to agent/grpc-external/services/dataplane/get_supported_features.go index cb4eff1e77..79041aa04a 100644 --- a/agent/grpc/public/services/dataplane/get_supported_features.go +++ b/agent/grpc-external/services/dataplane/get_supported_features.go @@ -7,19 +7,19 @@ import ( "google.golang.org/grpc/status" acl "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" structs "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto-public/pbdataplane" ) func (s *Server) GetSupportedDataplaneFeatures(ctx context.Context, req *pbdataplane.GetSupportedDataplaneFeaturesRequest) (*pbdataplane.GetSupportedDataplaneFeaturesResponse, error) { - logger := s.Logger.Named("get-supported-dataplane-features").With("request_id", public.TraceID()) + logger := s.Logger.Named("get-supported-dataplane-features").With("request_id", external.TraceID()) logger.Trace("Started processing request") defer logger.Trace("Finished processing request") // Require the given ACL token to have `service:write` on any service - token := public.TokenFromContext(ctx) + token := external.TokenFromContext(ctx) var authzContext acl.AuthorizerContext entMeta := structs.WildcardEnterpriseMetaInPartition(structs.WildcardSpecifier) authz, err := s.ACLResolver.ResolveTokenAndDefaultMeta(token, entMeta, &authzContext) diff --git a/agent/grpc/public/services/dataplane/get_supported_features_test.go b/agent/grpc-external/services/dataplane/get_supported_features_test.go similarity index 89% rename from agent/grpc/public/services/dataplane/get_supported_features_test.go rename to agent/grpc-external/services/dataplane/get_supported_features_test.go index bdcd0d455d..822fd6b5b4 100644 --- a/agent/grpc/public/services/dataplane/get_supported_features_test.go +++ b/agent/grpc-external/services/dataplane/get_supported_features_test.go @@ -12,8 +12,8 @@ import ( "github.com/hashicorp/consul/acl" resolver "github.com/hashicorp/consul/acl/resolver" - "github.com/hashicorp/consul/agent/grpc/public" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + external "github.com/hashicorp/consul/agent/grpc-external" + "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/proto-public/pbdataplane" ) @@ -24,7 +24,7 @@ func TestSupportedDataplaneFeatures_Success(t *testing.T) { aclResolver := &MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", testACLToken, mock.Anything, mock.Anything). Return(testutils.TestAuthorizerServiceWriteAny(t), nil) - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) server := NewServer(Config{ Logger: hclog.NewNullLogger(), ACLResolver: aclResolver, @@ -53,7 +53,7 @@ func TestSupportedDataplaneFeatures_Unauthenticated(t *testing.T) { aclResolver := &MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", mock.Anything, mock.Anything, mock.Anything). Return(resolver.Result{}, acl.ErrNotFound) - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) server := NewServer(Config{ Logger: hclog.NewNullLogger(), ACLResolver: aclResolver, @@ -70,7 +70,7 @@ func TestSupportedDataplaneFeatures_PermissionDenied(t *testing.T) { aclResolver := &MockACLResolver{} aclResolver.On("ResolveTokenAndDefaultMeta", testACLToken, mock.Anything, mock.Anything). Return(testutils.TestAuthorizerDenyAll(t), nil) - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) server := NewServer(Config{ Logger: hclog.NewNullLogger(), ACLResolver: aclResolver, diff --git a/agent/grpc/public/services/dataplane/mock_ACLResolver.go b/agent/grpc-external/services/dataplane/mock_ACLResolver.go similarity index 100% rename from agent/grpc/public/services/dataplane/mock_ACLResolver.go rename to agent/grpc-external/services/dataplane/mock_ACLResolver.go diff --git a/agent/grpc/public/services/dataplane/server.go b/agent/grpc-external/services/dataplane/server.go similarity index 100% rename from agent/grpc/public/services/dataplane/server.go rename to agent/grpc-external/services/dataplane/server.go diff --git a/agent/grpc/public/services/dataplane/server_test.go b/agent/grpc-external/services/dataplane/server_test.go similarity index 89% rename from agent/grpc/public/services/dataplane/server_test.go rename to agent/grpc-external/services/dataplane/server_test.go index fa0a24b91f..5ca346a6e1 100644 --- a/agent/grpc/public/services/dataplane/server_test.go +++ b/agent/grpc-external/services/dataplane/server_test.go @@ -4,7 +4,7 @@ import ( "context" "testing" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/proto-public/pbdataplane" "github.com/stretchr/testify/require" "google.golang.org/grpc" diff --git a/agent/rpc/peering/health_snapshot.go b/agent/grpc-external/services/peerstream/health_snapshot.go similarity index 99% rename from agent/rpc/peering/health_snapshot.go rename to agent/grpc-external/services/peerstream/health_snapshot.go index 8d73dcea45..c6cb3243b3 100644 --- a/agent/rpc/peering/health_snapshot.go +++ b/agent/grpc-external/services/peerstream/health_snapshot.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "github.com/hashicorp/consul/agent/structs" diff --git a/agent/rpc/peering/health_snapshot_test.go b/agent/grpc-external/services/peerstream/health_snapshot_test.go similarity index 99% rename from agent/rpc/peering/health_snapshot_test.go rename to agent/grpc-external/services/peerstream/health_snapshot_test.go index 33f662750d..74731b55fa 100644 --- a/agent/rpc/peering/health_snapshot_test.go +++ b/agent/grpc-external/services/peerstream/health_snapshot_test.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "testing" diff --git a/agent/grpc-external/services/peerstream/mock_ACLResolver.go b/agent/grpc-external/services/peerstream/mock_ACLResolver.go new file mode 100644 index 0000000000..d0e6720887 --- /dev/null +++ b/agent/grpc-external/services/peerstream/mock_ACLResolver.go @@ -0,0 +1,48 @@ +// Code generated by mockery v2.12.2. DO NOT EDIT. + +package peerstream + +import ( + acl "github.com/hashicorp/consul/acl" + mock "github.com/stretchr/testify/mock" + + resolver "github.com/hashicorp/consul/acl/resolver" + + testing "testing" +) + +// MockACLResolver is an autogenerated mock type for the ACLResolver type +type MockACLResolver struct { + mock.Mock +} + +// ResolveTokenAndDefaultMeta provides a mock function with given fields: _a0, _a1, _a2 +func (_m *MockACLResolver) ResolveTokenAndDefaultMeta(_a0 string, _a1 *acl.EnterpriseMeta, _a2 *acl.AuthorizerContext) (resolver.Result, error) { + ret := _m.Called(_a0, _a1, _a2) + + var r0 resolver.Result + if rf, ok := ret.Get(0).(func(string, *acl.EnterpriseMeta, *acl.AuthorizerContext) resolver.Result); ok { + r0 = rf(_a0, _a1, _a2) + } else { + r0 = ret.Get(0).(resolver.Result) + } + + var r1 error + if rf, ok := ret.Get(1).(func(string, *acl.EnterpriseMeta, *acl.AuthorizerContext) error); ok { + r1 = rf(_a0, _a1, _a2) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewMockACLResolver creates a new instance of MockACLResolver. It also registers the testing.TB interface on the mock and a cleanup function to assert the mocks expectations. +func NewMockACLResolver(t testing.TB) *MockACLResolver { + mock := &MockACLResolver{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/agent/rpc/peering/replication.go b/agent/grpc-external/services/peerstream/replication.go similarity index 77% rename from agent/rpc/peering/replication.go rename to agent/grpc-external/services/peerstream/replication.go index aef8b45255..f9f5ce76b0 100644 --- a/agent/rpc/peering/replication.go +++ b/agent/grpc-external/services/peerstream/replication.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "errors" @@ -7,7 +7,6 @@ import ( "github.com/golang/protobuf/proto" "github.com/golang/protobuf/ptypes" - "github.com/hashicorp/consul/types" "github.com/hashicorp/go-hclog" "google.golang.org/genproto/googleapis/rpc/code" "google.golang.org/protobuf/types/known/anypb" @@ -15,8 +14,10 @@ import ( "github.com/hashicorp/consul/agent/cache" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/pbpeering" + "github.com/hashicorp/consul/proto/pbpeerstream" "github.com/hashicorp/consul/proto/pbservice" "github.com/hashicorp/consul/proto/pbstatus" + "github.com/hashicorp/consul/types" ) /* @@ -37,12 +38,10 @@ import ( func makeServiceResponse( logger hclog.Logger, update cache.UpdateEvent, -) *pbpeering.ReplicationMessage { +) (*pbpeerstream.ReplicationMessage_Response, error) { any, csn, err := marshalToProtoAny[*pbservice.IndexedCheckServiceNodes](update.Result) if err != nil { - // Log the error and skip this response to avoid locking up peering due to a bad update event. - logger.Error("failed to marshal", "error", err) - return nil + return nil, fmt.Errorf("failed to marshal: %w", err) } serviceName := strings.TrimPrefix(update.CorrelationID, subExportedService) @@ -55,60 +54,43 @@ func makeServiceResponse( // We don't distinguish when these three things occurred, but it's safe to send a DELETE Op in all cases, so we do that. // Case #1 is a no-op for the importing peer. if len(csn.Nodes) == 0 { - resp := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Response_{ - Response: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, - // TODO(peering): Nonce management - Nonce: "", - ResourceID: serviceName, - Operation: pbpeering.ReplicationMessage_Response_DELETE, - }, - }, - } - return resp + return &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLService, + // TODO(peering): Nonce management + Nonce: "", + ResourceID: serviceName, + Operation: pbpeerstream.Operation_OPERATION_DELETE, + }, nil } // If there are nodes in the response, we push them as an UPSERT operation. - resp := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Response_{ - Response: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, - // TODO(peering): Nonce management - Nonce: "", - ResourceID: serviceName, - Operation: pbpeering.ReplicationMessage_Response_UPSERT, - Resource: any, - }, - }, - } - return resp + return &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLService, + // TODO(peering): Nonce management + Nonce: "", + ResourceID: serviceName, + Operation: pbpeerstream.Operation_OPERATION_UPSERT, + Resource: any, + }, nil } func makeCARootsResponse( logger hclog.Logger, update cache.UpdateEvent, -) *pbpeering.ReplicationMessage { +) (*pbpeerstream.ReplicationMessage_Response, error) { any, _, err := marshalToProtoAny[*pbpeering.PeeringTrustBundle](update.Result) if err != nil { - // Log the error and skip this response to avoid locking up peering due to a bad update event. - logger.Error("failed to marshal", "error", err) - return nil + return nil, fmt.Errorf("failed to marshal: %w", err) } - resp := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Response_{ - Response: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLRoots, - // TODO(peering): Nonce management - Nonce: "", - ResourceID: "roots", - Operation: pbpeering.ReplicationMessage_Response_UPSERT, - Resource: any, - }, - }, - } - return resp + return &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLRoots, + // TODO(peering): Nonce management + Nonce: "", + ResourceID: "roots", + Operation: pbpeerstream.Operation_OPERATION_UPSERT, + Resource: any, + }, nil } // marshalToProtoAny takes any input and returns: @@ -128,14 +110,14 @@ func marshalToProtoAny[T proto.Message](in any) (*anypb.Any, T, error) { return any, typ, nil } -func (s *Service) processResponse( +func (s *Server) processResponse( peerName string, partition string, - resp *pbpeering.ReplicationMessage_Response, -) (*pbpeering.ReplicationMessage, error) { - if !pbpeering.KnownTypeURL(resp.ResourceURL) { + resp *pbpeerstream.ReplicationMessage_Response, +) (*pbpeerstream.ReplicationMessage, error) { + if !pbpeerstream.KnownTypeURL(resp.ResourceURL) { err := fmt.Errorf("received response for unknown resource type %q", resp.ResourceURL) - return makeReply( + return makeNACKReply( resp.ResourceURL, resp.Nonce, code.Code_INVALID_ARGUMENT, @@ -144,10 +126,10 @@ func (s *Service) processResponse( } switch resp.Operation { - case pbpeering.ReplicationMessage_Response_UPSERT: + case pbpeerstream.Operation_OPERATION_UPSERT: if resp.Resource == nil { err := fmt.Errorf("received upsert response with no content") - return makeReply( + return makeNACKReply( resp.ResourceURL, resp.Nonce, code.Code_INVALID_ARGUMENT, @@ -156,7 +138,7 @@ func (s *Service) processResponse( } if err := s.handleUpsert(peerName, partition, resp.ResourceURL, resp.ResourceID, resp.Resource); err != nil { - return makeReply( + return makeNACKReply( resp.ResourceURL, resp.Nonce, code.Code_INTERNAL, @@ -164,27 +146,27 @@ func (s *Service) processResponse( ), fmt.Errorf("upsert error: %w", err) } - return makeReply(resp.ResourceURL, resp.Nonce, code.Code_OK, ""), nil + return makeACKReply(resp.ResourceURL, resp.Nonce), nil - case pbpeering.ReplicationMessage_Response_DELETE: + case pbpeerstream.Operation_OPERATION_DELETE: if err := s.handleDelete(peerName, partition, resp.ResourceURL, resp.ResourceID); err != nil { - return makeReply( + return makeNACKReply( resp.ResourceURL, resp.Nonce, code.Code_INTERNAL, fmt.Sprintf("delete error, ResourceURL: %q, ResourceID: %q: %v", resp.ResourceURL, resp.ResourceID, err), ), fmt.Errorf("delete error: %w", err) } - return makeReply(resp.ResourceURL, resp.Nonce, code.Code_OK, ""), nil + return makeACKReply(resp.ResourceURL, resp.Nonce), nil default: var errMsg string - if op := pbpeering.ReplicationMessage_Response_Operation_name[int32(resp.Operation)]; op != "" { + if op := pbpeerstream.Operation_name[int32(resp.Operation)]; op != "" { errMsg = fmt.Sprintf("unsupported operation: %q", op) } else { errMsg = fmt.Sprintf("unsupported operation: %d", resp.Operation) } - return makeReply( + return makeNACKReply( resp.ResourceURL, resp.Nonce, code.Code_INVALID_ARGUMENT, @@ -193,7 +175,7 @@ func (s *Service) processResponse( } } -func (s *Service) handleUpsert( +func (s *Server) handleUpsert( peerName string, partition string, resourceURL string, @@ -201,7 +183,7 @@ func (s *Service) handleUpsert( resource *anypb.Any, ) error { switch resourceURL { - case pbpeering.TypeURLService: + case pbpeerstream.TypeURLService: sn := structs.ServiceNameFromString(resourceID) sn.OverridePartition(partition) @@ -212,7 +194,7 @@ func (s *Service) handleUpsert( return s.handleUpdateService(peerName, partition, sn, csn) - case pbpeering.TypeURLRoots: + case pbpeerstream.TypeURLRoots: roots := &pbpeering.PeeringTrustBundle{} if err := ptypes.UnmarshalAny(resource, roots); err != nil { return fmt.Errorf("failed to unmarshal resource: %w", err) @@ -233,14 +215,14 @@ func (s *Service) handleUpsert( // On a DELETE event: // - A reconciliation against nil or empty input pbNodes leads to deleting all stored catalog resources // associated with the service name. -func (s *Service) handleUpdateService( +func (s *Server) handleUpdateService( peerName string, partition string, sn structs.ServiceName, pbNodes *pbservice.IndexedCheckServiceNodes, ) error { // Capture instances in the state store for reconciliation later. - _, storedInstances, err := s.Backend.Store().CheckServiceNodes(nil, sn.Name, &sn.EnterpriseMeta, peerName) + _, storedInstances, err := s.GetStore().CheckServiceNodes(nil, sn.Name, &sn.EnterpriseMeta, peerName) if err != nil { return fmt.Errorf("failed to read imported services: %w", err) } @@ -256,14 +238,14 @@ func (s *Service) handleUpdateService( for _, nodeSnap := range snap.Nodes { // First register the node req := nodeSnap.Node.ToRegisterRequest() - if err := s.Backend.Apply().CatalogRegister(&req); err != nil { + if err := s.Backend.CatalogRegister(&req); err != nil { return fmt.Errorf("failed to register node: %w", err) } // Then register all services on that node for _, svcSnap := range nodeSnap.Services { req.Service = svcSnap.Service - if err := s.Backend.Apply().CatalogRegister(&req); err != nil { + if err := s.Backend.CatalogRegister(&req); err != nil { return fmt.Errorf("failed to register service: %w", err) } } @@ -278,7 +260,7 @@ func (s *Service) handleUpdateService( } req.Checks = chks - if err := s.Backend.Apply().CatalogRegister(&req); err != nil { + if err := s.Backend.CatalogRegister(&req); err != nil { return fmt.Errorf("failed to register check: %w", err) } } @@ -315,7 +297,7 @@ func (s *Service) handleUpdateService( // instance is not in the snapshot either, since a service instance can't // exist without a node. // This will also delete all service checks. - err := s.Backend.Apply().CatalogDeregister(&structs.DeregisterRequest{ + err := s.Backend.CatalogDeregister(&structs.DeregisterRequest{ Node: csn.Node.Node, ServiceID: csn.Service.ID, EnterpriseMeta: csn.Service.EnterpriseMeta, @@ -335,7 +317,7 @@ func (s *Service) handleUpdateService( // Delete the service instance if not in the snapshot. sid := csn.Service.CompoundServiceID() if _, ok := snap.Nodes[csn.Node.ID].Services[sid]; !ok { - err := s.Backend.Apply().CatalogDeregister(&structs.DeregisterRequest{ + err := s.Backend.CatalogDeregister(&structs.DeregisterRequest{ Node: csn.Node.Node, ServiceID: csn.Service.ID, EnterpriseMeta: csn.Service.EnterpriseMeta, @@ -369,7 +351,7 @@ func (s *Service) handleUpdateService( // If the check isn't a node check then it's a service check. // Service checks that were not present can be deleted immediately because // checks for a given service ID will only be attached to a single CheckServiceNode. - err := s.Backend.Apply().CatalogDeregister(&structs.DeregisterRequest{ + err := s.Backend.CatalogDeregister(&structs.DeregisterRequest{ Node: chk.Node, CheckID: chk.CheckID, EnterpriseMeta: chk.EnterpriseMeta, @@ -387,7 +369,7 @@ func (s *Service) handleUpdateService( // Delete all deduplicated node checks. for chk := range deletedNodeChecks { nodeMeta := structs.NodeEnterpriseMetaInPartition(sn.PartitionOrDefault()) - err := s.Backend.Apply().CatalogDeregister(&structs.DeregisterRequest{ + err := s.Backend.CatalogDeregister(&structs.DeregisterRequest{ Node: chk.node, CheckID: chk.checkID, EnterpriseMeta: *nodeMeta, @@ -402,7 +384,7 @@ func (s *Service) handleUpdateService( // Delete any nodes that do not have any other services registered on them. for node := range unusedNodes { nodeMeta := structs.NodeEnterpriseMetaInPartition(sn.PartitionOrDefault()) - _, ns, err := s.Backend.Store().NodeServices(nil, node, nodeMeta, peerName) + _, ns, err := s.GetStore().NodeServices(nil, node, nodeMeta, peerName) if err != nil { return fmt.Errorf("failed to query services on node: %w", err) } @@ -412,7 +394,7 @@ func (s *Service) handleUpdateService( } // All services on the node were deleted, so the node is also cleaned up. - err = s.Backend.Apply().CatalogDeregister(&structs.DeregisterRequest{ + err = s.Backend.CatalogDeregister(&structs.DeregisterRequest{ Node: node, PeerName: peerName, EnterpriseMeta: *nodeMeta, @@ -425,7 +407,7 @@ func (s *Service) handleUpdateService( return nil } -func (s *Service) handleUpsertRoots( +func (s *Server) handleUpsertRoots( peerName string, partition string, trustBundle *pbpeering.PeeringTrustBundle, @@ -437,17 +419,17 @@ func (s *Service) handleUpsertRoots( req := &pbpeering.PeeringTrustBundleWriteRequest{ PeeringTrustBundle: trustBundle, } - return s.Backend.Apply().PeeringTrustBundleWrite(req) + return s.Backend.PeeringTrustBundleWrite(req) } -func (s *Service) handleDelete( +func (s *Server) handleDelete( peerName string, partition string, resourceURL string, resourceID string, ) error { switch resourceURL { - case pbpeering.TypeURLService: + case pbpeerstream.TypeURLService: sn := structs.ServiceNameFromString(resourceID) sn.OverridePartition(partition) return s.handleUpdateService(peerName, partition, sn, nil) @@ -457,7 +439,14 @@ func (s *Service) handleDelete( } } -func makeReply(resourceURL, nonce string, errCode code.Code, errMsg string) *pbpeering.ReplicationMessage { +func makeACKReply(resourceURL, nonce string) *pbpeerstream.ReplicationMessage { + return makeReplicationRequest(&pbpeerstream.ReplicationMessage_Request{ + ResourceURL: resourceURL, + ResponseNonce: nonce, + }) +} + +func makeNACKReply(resourceURL, nonce string, errCode code.Code, errMsg string) *pbpeerstream.ReplicationMessage { var rpcErr *pbstatus.Status if errCode != code.Code_OK || errMsg != "" { rpcErr = &pbstatus.Status{ @@ -466,14 +455,27 @@ func makeReply(resourceURL, nonce string, errCode code.Code, errMsg string) *pbp } } - // TODO: shouldn't this be response? - return &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: resourceURL, - Nonce: nonce, - Error: rpcErr, - }, + return makeReplicationRequest(&pbpeerstream.ReplicationMessage_Request{ + ResourceURL: resourceURL, + ResponseNonce: nonce, + Error: rpcErr, + }) +} + +// makeReplicationRequest is a convenience method to make a Request-type ReplicationMessage. +func makeReplicationRequest(req *pbpeerstream.ReplicationMessage_Request) *pbpeerstream.ReplicationMessage { + return &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: req, + }, + } +} + +// makeReplicationResponse is a convenience method to make a Response-type ReplicationMessage. +func makeReplicationResponse(resp *pbpeerstream.ReplicationMessage_Response) *pbpeerstream.ReplicationMessage { + return &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Response_{ + Response: resp, }, } } diff --git a/agent/grpc-external/services/peerstream/server.go b/agent/grpc-external/services/peerstream/server.go new file mode 100644 index 0000000000..a71c30d31a --- /dev/null +++ b/agent/grpc-external/services/peerstream/server.go @@ -0,0 +1,101 @@ +package peerstream + +import ( + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-memdb" + "google.golang.org/grpc" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/acl/resolver" + "github.com/hashicorp/consul/agent/consul/state" + "github.com/hashicorp/consul/agent/consul/stream" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/proto/pbpeering" + "github.com/hashicorp/consul/proto/pbpeerstream" +) + +// TODO(peering): fix up these interfaces to be more testable now that they are +// extracted from private peering + +type Server struct { + Config +} + +type Config struct { + Backend Backend + Tracker *Tracker + GetStore func() StateStore + Logger hclog.Logger + ACLResolver ACLResolver + // Datacenter of the Consul server this gRPC server is hosted on + Datacenter string + ConnectEnabled bool +} + +//go:generate mockery --name ACLResolver --inpackage +type ACLResolver interface { + ResolveTokenAndDefaultMeta(string, *acl.EnterpriseMeta, *acl.AuthorizerContext) (resolver.Result, error) +} + +func NewServer(cfg Config) *Server { + requireNotNil(cfg.Backend, "Backend") + requireNotNil(cfg.Tracker, "Tracker") + requireNotNil(cfg.GetStore, "GetStore") + requireNotNil(cfg.Logger, "Logger") + // requireNotNil(cfg.ACLResolver, "ACLResolver") // TODO(peering): reenable check when ACLs are required + if cfg.Datacenter == "" { + panic("Datacenter is required") + } + return &Server{ + Config: cfg, + } +} + +func requireNotNil(v interface{}, name string) { + if v == nil { + panic(name + " is required") + } +} + +var _ pbpeerstream.PeerStreamServiceServer = (*Server)(nil) + +func (s *Server) Register(grpcServer *grpc.Server) { + pbpeerstream.RegisterPeerStreamServiceServer(grpcServer, s) +} + +type Backend interface { + Subscribe(req *stream.SubscribeRequest) (*stream.Subscription, error) + + // IsLeader indicates whether the consul server is in a leader state or not. + IsLeader() bool + + // SetLeaderAddress is called on a raft.LeaderObservation in a go routine + // in the consul server; see trackLeaderChanges() + SetLeaderAddress(string) + + // GetLeaderAddress provides the best hint for the current address of the + // leader. There is no guarantee that this is the actual address of the + // leader. + GetLeaderAddress() string + + PeeringTerminateByID(req *pbpeering.PeeringTerminateByIDRequest) error + PeeringTrustBundleWrite(req *pbpeering.PeeringTrustBundleWriteRequest) error + CatalogRegister(req *structs.RegisterRequest) error + CatalogDeregister(req *structs.DeregisterRequest) error +} + +// StateStore provides a read-only interface for querying Peering data. +type StateStore interface { + PeeringRead(ws memdb.WatchSet, q state.Query) (uint64, *pbpeering.Peering, error) + PeeringReadByID(ws memdb.WatchSet, id string) (uint64, *pbpeering.Peering, error) + PeeringList(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.Peering, error) + PeeringTrustBundleRead(ws memdb.WatchSet, q state.Query) (uint64, *pbpeering.PeeringTrustBundle, error) + PeeringTrustBundleList(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.PeeringTrustBundle, error) + ExportedServicesForPeer(ws memdb.WatchSet, peerID, dc string) (uint64, *structs.ExportedServiceList, error) + ServiceDump(ws memdb.WatchSet, kind structs.ServiceKind, useKind bool, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) + CheckServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) + NodeServices(ws memdb.WatchSet, nodeNameOrID string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.NodeServices, error) + CAConfig(ws memdb.WatchSet) (uint64, *structs.CAConfiguration, error) + TrustBundleListByService(ws memdb.WatchSet, service, dc string, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.PeeringTrustBundle, error) + AbandonCh() <-chan struct{} +} diff --git a/agent/grpc-external/services/peerstream/stream_resources.go b/agent/grpc-external/services/peerstream/stream_resources.go new file mode 100644 index 0000000000..6113400827 --- /dev/null +++ b/agent/grpc-external/services/peerstream/stream_resources.go @@ -0,0 +1,422 @@ +package peerstream + +import ( + "context" + "fmt" + "io" + "strings" + + "github.com/golang/protobuf/jsonpb" + "github.com/golang/protobuf/proto" + "github.com/hashicorp/go-hclog" + "google.golang.org/genproto/googleapis/rpc/code" + "google.golang.org/grpc/codes" + grpcstatus "google.golang.org/grpc/status" + + "github.com/hashicorp/consul/agent/connect" + external "github.com/hashicorp/consul/agent/grpc-external" + "github.com/hashicorp/consul/proto/pbpeering" + "github.com/hashicorp/consul/proto/pbpeerstream" +) + +type BidirectionalStream interface { + Send(*pbpeerstream.ReplicationMessage) error + Recv() (*pbpeerstream.ReplicationMessage, error) + Context() context.Context +} + +// StreamResources handles incoming streaming connections. +func (s *Server) StreamResources(stream pbpeerstream.PeerStreamService_StreamResourcesServer) error { + logger := s.Logger.Named("stream-resources").With("request_id", external.TraceID()) + + logger.Trace("Started processing request") + defer logger.Trace("Finished processing request") + + // NOTE: this code should have similar error handling to the new-request + // handling code in HandleStream() + + if !s.Backend.IsLeader() { + // we are not the leader so we will hang up on the dialer + + logger.Error("cannot establish a peering stream on a follower node") + + st, err := grpcstatus.New(codes.FailedPrecondition, + "cannot establish a peering stream on a follower node").WithDetails( + &pbpeerstream.LeaderAddress{Address: s.Backend.GetLeaderAddress()}) + if err != nil { + logger.Error(fmt.Sprintf("failed to marshal the leader address in response; err: %v", err)) + return grpcstatus.Error(codes.FailedPrecondition, "cannot establish a peering stream on a follower node") + } else { + return st.Err() + } + } + + // Initial message on a new stream must be a new subscription request. + first, err := stream.Recv() + if err != nil { + logger.Error("failed to establish stream", "error", err) + return err + } + + // TODO(peering) Make request contain a list of resources, so that roots and services can be + // subscribed to with a single request. See: + // https://github.com/envoyproxy/data-plane-api/blob/main/envoy/service/discovery/v3/discovery.proto#L46 + req := first.GetRequest() + if req == nil { + return grpcstatus.Error(codes.InvalidArgument, "first message when initiating a peering must be a subscription request") + } + logger.Trace("received initial replication request from peer") + logTraceRecv(logger, req) + + if req.PeerID == "" { + return grpcstatus.Error(codes.InvalidArgument, "initial subscription request must specify a PeerID") + } + if req.ResponseNonce != "" { + return grpcstatus.Error(codes.InvalidArgument, "initial subscription request must not contain a nonce") + } + if req.Error != nil { + return grpcstatus.Error(codes.InvalidArgument, "initial subscription request must not contain an error") + } + if !pbpeerstream.KnownTypeURL(req.ResourceURL) { + return grpcstatus.Errorf(codes.InvalidArgument, "subscription request to unknown resource URL: %s", req.ResourceURL) + } + + _, p, err := s.GetStore().PeeringReadByID(nil, req.PeerID) + if err != nil { + logger.Error("failed to look up peer", "peer_id", req.PeerID, "error", err) + return grpcstatus.Error(codes.Internal, "failed to find PeerID: "+req.PeerID) + } + if p == nil { + return grpcstatus.Error(codes.InvalidArgument, "initial subscription for unknown PeerID: "+req.PeerID) + } + + // TODO(peering): If the peering is marked as deleted, send a Terminated message and return + // TODO(peering): Store subscription request so that an event publisher can separately handle pushing messages for it + logger.Info("accepted initial replication request from peer", "peer_id", p.ID) + + if p.PeerID != "" { + return grpcstatus.Error(codes.InvalidArgument, "expected PeerID to be empty; the wrong end of peering is being dialed") + } + + streamReq := HandleStreamRequest{ + LocalID: p.ID, + RemoteID: "", + PeerName: p.Name, + Partition: p.Partition, + Stream: stream, + } + err = s.HandleStream(streamReq) + // A nil error indicates that the peering was deleted and the stream needs to be gracefully shutdown. + if err == nil { + s.DrainStream(streamReq) + return nil + } + + logger.Error("error handling stream", "peer_name", p.Name, "peer_id", req.PeerID, "error", err) + return err +} + +type HandleStreamRequest struct { + // LocalID is the UUID for the peering in the local Consul datacenter. + LocalID string + + // RemoteID is the UUID for the peering from the perspective of the peer. + RemoteID string + + // PeerName is the name of the peering. + PeerName string + + // Partition is the local partition associated with the peer. + Partition string + + // Stream is the open stream to the peer cluster. + Stream BidirectionalStream +} + +func (r HandleStreamRequest) WasDialed() bool { + return r.RemoteID == "" +} + +// DrainStream attempts to gracefully drain the stream when the connection is going to be torn down. +// Tearing down the connection too quickly can lead our peer receiving a context cancellation error before the stream termination message. +// Handling the termination message is important to set the expectation that the peering will not be reestablished unless recreated. +func (s *Server) DrainStream(req HandleStreamRequest) { + for { + // Ensure that we read until an error, or the peer has nothing more to send. + if _, err := req.Stream.Recv(); err != nil { + if err != io.EOF { + s.Logger.Warn("failed to tear down stream gracefully: peer may not have received termination message", + "peer_name", req.PeerName, "peer_id", req.LocalID, "error", err) + } + break + } + // Since the peering is being torn down we discard all replication messages without an error. + // We want to avoid importing new data at this point. + } +} + +// The localID provided is the locally-generated identifier for the peering. +// The remoteID is an identifier that the remote peer recognizes for the peering. +func (s *Server) HandleStream(streamReq HandleStreamRequest) error { + // TODO: pass logger down from caller? + logger := s.Logger.Named("stream"). + With("peer_name", streamReq.PeerName). + With("peer_id", streamReq.LocalID). + With("dialed", streamReq.WasDialed()) + logger.Trace("handling stream for peer") + + status, err := s.Tracker.Connected(streamReq.LocalID) + if err != nil { + return fmt.Errorf("failed to register stream: %v", err) + } + + // TODO(peering) Also need to clear subscriptions associated with the peer + defer s.Tracker.Disconnected(streamReq.LocalID) + + var trustDomain string + if s.ConnectEnabled { + // Read the TrustDomain up front - we do not allow users to change the ClusterID + // so reading it once at the beginning of the stream is sufficient. + trustDomain, err = getTrustDomain(s.GetStore(), logger) + if err != nil { + return err + } + } + + mgr := newSubscriptionManager( + streamReq.Stream.Context(), + logger, + s.Config, + trustDomain, + s.Backend, + s.GetStore, + ) + subCh := mgr.subscribe(streamReq.Stream.Context(), streamReq.LocalID, streamReq.PeerName, streamReq.Partition) + + sub := makeReplicationRequest(&pbpeerstream.ReplicationMessage_Request{ + ResourceURL: pbpeerstream.TypeURLService, + PeerID: streamReq.RemoteID, + }) + logTraceSend(logger, sub) + + if err := streamReq.Stream.Send(sub); err != nil { + if err == io.EOF { + logger.Info("stream ended by peer") + status.TrackReceiveError(err.Error()) + return nil + } + // TODO(peering) Test error handling in calls to Send/Recv + status.TrackSendError(err.Error()) + return fmt.Errorf("failed to send to stream: %v", err) + } + + // TODO(peering): Should this be buffered? + recvChan := make(chan *pbpeerstream.ReplicationMessage) + go func() { + defer close(recvChan) + for { + msg, err := streamReq.Stream.Recv() + if err == nil { + logTraceRecv(logger, msg) + recvChan <- msg + continue + } + + if err == io.EOF { + logger.Info("stream ended by peer") + status.TrackReceiveError(err.Error()) + return + } + logger.Error("failed to receive from stream", "error", err) + status.TrackReceiveError(err.Error()) + return + } + }() + + for { + select { + // When the doneCh is closed that means that the peering was deleted locally. + case <-status.Done(): + logger.Info("ending stream") + + term := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Terminated_{ + Terminated: &pbpeerstream.ReplicationMessage_Terminated{}, + }, + } + logTraceSend(logger, term) + + if err := streamReq.Stream.Send(term); err != nil { + status.TrackSendError(err.Error()) + return fmt.Errorf("failed to send to stream: %v", err) + } + + logger.Trace("deleting stream status") + s.Tracker.DeleteStatus(streamReq.LocalID) + + return nil + + case msg, open := <-recvChan: + if !open { + logger.Trace("no longer receiving data on the stream") + return nil + } + + // NOTE: this code should have similar error handling to the + // initial handling code in StreamResources() + + if !s.Backend.IsLeader() { + // we are not the leader anymore so we will hang up on the dialer + logger.Error("node is not a leader anymore; cannot continue streaming") + + st, err := grpcstatus.New(codes.FailedPrecondition, + "node is not a leader anymore; cannot continue streaming").WithDetails( + &pbpeerstream.LeaderAddress{Address: s.Backend.GetLeaderAddress()}) + if err != nil { + logger.Error(fmt.Sprintf("failed to marshal the leader address in response; err: %v", err)) + return grpcstatus.Error(codes.FailedPrecondition, "node is not a leader anymore; cannot continue streaming") + } else { + return st.Err() + } + } + + if req := msg.GetRequest(); req != nil { + if !pbpeerstream.KnownTypeURL(req.ResourceURL) { + return grpcstatus.Errorf(codes.InvalidArgument, "subscription request to unknown resource URL: %s", req.ResourceURL) + } + switch { + case req.ResponseNonce == "": + // TODO(peering): This can happen on a client peer since they don't try to receive subscriptions before entering HandleStream. + // Should change that behavior or only allow it that one time. + + case req.Error != nil && (req.Error.Code != int32(code.Code_OK) || req.Error.Message != ""): + logger.Warn("client peer was unable to apply resource", "code", req.Error.Code, "error", req.Error.Message) + status.TrackNack(fmt.Sprintf("client peer was unable to apply resource: %s", req.Error.Message)) + + default: + status.TrackAck() + } + + continue + } + + if resp := msg.GetResponse(); resp != nil { + // TODO(peering): Ensure there's a nonce + reply, err := s.processResponse(streamReq.PeerName, streamReq.Partition, resp) + if err != nil { + logger.Error("failed to persist resource", "resourceURL", resp.ResourceURL, "resourceID", resp.ResourceID) + status.TrackReceiveError(err.Error()) + } else { + status.TrackReceiveSuccess() + } + + logTraceSend(logger, reply) + if err := streamReq.Stream.Send(reply); err != nil { + status.TrackSendError(err.Error()) + return fmt.Errorf("failed to send to stream: %v", err) + } + + continue + } + + if term := msg.GetTerminated(); term != nil { + logger.Info("peering was deleted by our peer: marking peering as terminated and cleaning up imported resources") + + // Once marked as terminated, a separate deferred deletion routine will clean up imported resources. + if err := s.Backend.PeeringTerminateByID(&pbpeering.PeeringTerminateByIDRequest{ID: streamReq.LocalID}); err != nil { + logger.Error("failed to mark peering as terminated: %w", err) + } + return nil + } + + case update := <-subCh: + var resp *pbpeerstream.ReplicationMessage_Response + switch { + case strings.HasPrefix(update.CorrelationID, subExportedService): + resp, err = makeServiceResponse(logger, update) + if err != nil { + // Log the error and skip this response to avoid locking up peering due to a bad update event. + logger.Error("failed to create service response", "error", err) + continue + } + + case strings.HasPrefix(update.CorrelationID, subMeshGateway): + // TODO(Peering): figure out how to sync this separately + + case update.CorrelationID == subCARoot: + resp, err = makeCARootsResponse(logger, update) + if err != nil { + // Log the error and skip this response to avoid locking up peering due to a bad update event. + logger.Error("failed to create ca roots response", "error", err) + continue + } + + default: + logger.Warn("unrecognized update type from subscription manager: " + update.CorrelationID) + continue + } + if resp == nil { + continue + } + + replResp := makeReplicationResponse(resp) + + logTraceSend(logger, replResp) + if err := streamReq.Stream.Send(replResp); err != nil { + status.TrackSendError(err.Error()) + return fmt.Errorf("failed to push data for %q: %w", update.CorrelationID, err) + } + } + } +} + +func getTrustDomain(store StateStore, logger hclog.Logger) (string, error) { + _, cfg, err := store.CAConfig(nil) + switch { + case err != nil: + logger.Error("failed to read Connect CA Config", "error", err) + return "", grpcstatus.Error(codes.Internal, "failed to read Connect CA Config") + case cfg == nil: + logger.Warn("cannot begin stream because Connect CA is not yet initialized") + return "", grpcstatus.Error(codes.FailedPrecondition, "Connect CA is not yet initialized") + } + return connect.SpiffeIDSigningForCluster(cfg.ClusterID).Host(), nil +} + +func (s *Server) StreamStatus(peer string) (resp Status, found bool) { + return s.Tracker.StreamStatus(peer) +} + +// ConnectedStreams returns a map of connected stream IDs to the corresponding channel for tearing them down. +func (s *Server) ConnectedStreams() map[string]chan struct{} { + return s.Tracker.ConnectedStreams() +} + +func logTraceRecv(logger hclog.Logger, pb proto.Message) { + logTraceProto(logger, pb, true) +} + +func logTraceSend(logger hclog.Logger, pb proto.Message) { + logTraceProto(logger, pb, false) +} + +func logTraceProto(logger hclog.Logger, pb proto.Message, received bool) { + if !logger.IsTrace() { + return + } + + dir := "sent" + if received { + dir = "received" + } + + m := jsonpb.Marshaler{ + Indent: " ", + } + out, err := m.MarshalToString(pb) + if err != nil { + out = "" + } + + logger.Trace("replication message", "direction", dir, "protobuf", out) +} diff --git a/agent/rpc/peering/stream_test.go b/agent/grpc-external/services/peerstream/stream_test.go similarity index 76% rename from agent/rpc/peering/stream_test.go rename to agent/grpc-external/services/peerstream/stream_test.go index 84b7507238..de1455a632 100644 --- a/agent/rpc/peering/stream_test.go +++ b/agent/grpc-external/services/peerstream/stream_test.go @@ -1,10 +1,14 @@ -package peering +package peerstream + +// TODO: rename this file to replication_test.go import ( "context" "fmt" "io" + "net" "sort" + "sync" "testing" "time" @@ -26,34 +30,24 @@ import ( "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/proto/pbcommon" "github.com/hashicorp/consul/proto/pbpeering" + "github.com/hashicorp/consul/proto/pbpeerstream" "github.com/hashicorp/consul/proto/pbservice" "github.com/hashicorp/consul/proto/pbstatus" "github.com/hashicorp/consul/proto/prototest" + "github.com/hashicorp/consul/sdk/freeport" "github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/consul/types" ) func TestStreamResources_Server_Follower(t *testing.T) { - publisher := stream.NewEventPublisher(10 * time.Second) - store := newStateStore(t, publisher) - - srv := NewService( - testutil.Logger(t), - Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, - &testStreamBackend{ - store: store, - pub: publisher, - leader: func() bool { - return false - }, - leaderAddress: &leaderAddress{ - addr: "expected:address", - }, - }) + srv, _ := newTestServer(t, func(c *Config) { + backend := c.Backend.(*testStreamBackend) + backend.leader = func() bool { + return false + } + backend.leaderAddr = "expected:address" + }) client := NewMockClient(context.Background()) @@ -81,39 +75,27 @@ func TestStreamResources_Server_Follower(t *testing.T) { deets := st.Details() // expect a LeaderAddress message - exp := []interface{}{&pbpeering.LeaderAddress{Address: "expected:address"}} + exp := []interface{}{&pbpeerstream.LeaderAddress{Address: "expected:address"}} prototest.AssertDeepEqual(t, exp, deets) } // TestStreamResources_Server_LeaderBecomesFollower simulates a srv that is a leader when the // subscription request is sent but loses leadership status for subsequent messages. func TestStreamResources_Server_LeaderBecomesFollower(t *testing.T) { - publisher := stream.NewEventPublisher(10 * time.Second) - store := newStateStore(t, publisher) + srv, store := newTestServer(t, func(c *Config) { + backend := c.Backend.(*testStreamBackend) - first := true - leaderFunc := func() bool { - if first { - first = false - return true + first := true + backend.leader = func() bool { + if first { + first = false + return true + } + return false } - return false - } - srv := NewService( - testutil.Logger(t), - Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, - &testStreamBackend{ - store: store, - pub: publisher, - leader: leaderFunc, - leaderAddress: &leaderAddress{ - addr: "expected:address", - }, - }) + backend.leaderAddr = "expected:address" + }) client := NewMockClient(context.Background()) @@ -127,18 +109,19 @@ func TestStreamResources_Server_LeaderBecomesFollower(t *testing.T) { } }() - p := writeEstablishedPeering(t, store, 1, "my-peer") + p := writePeeringToBeDialed(t, store, 1, "my-peer") + require.Empty(t, p.PeerID, "should be empty if being dialed") peerID := p.ID // Set the initial roots and CA configuration. _, _ = writeInitialRootsAndCA(t, store) // Receive a subscription from a peer - sub := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ + sub := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ PeerID: peerID, - ResourceURL: pbpeering.TypeURLService, + ResourceURL: pbpeerstream.TypeURLService, }, }, } @@ -152,13 +135,13 @@ func TestStreamResources_Server_LeaderBecomesFollower(t *testing.T) { receiveRoots, err := client.Recv() require.NoError(t, err) require.NotNil(t, receiveRoots.GetResponse()) - require.Equal(t, pbpeering.TypeURLRoots, receiveRoots.GetResponse().ResourceURL) + require.Equal(t, pbpeerstream.TypeURLRoots, receiveRoots.GetResponse().ResourceURL) - input2 := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: pbpeering.TypeURLService, - Nonce: "1", + input2 := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + ResourceURL: pbpeerstream.TypeURLService, + ResponseNonce: "1", }, }, } @@ -178,30 +161,19 @@ func TestStreamResources_Server_LeaderBecomesFollower(t *testing.T) { deets := st.Details() // expect a LeaderAddress message - exp := []interface{}{&pbpeering.LeaderAddress{Address: "expected:address"}} + exp := []interface{}{&pbpeerstream.LeaderAddress{Address: "expected:address"}} prototest.AssertDeepEqual(t, exp, deets) } func TestStreamResources_Server_FirstRequest(t *testing.T) { type testCase struct { name string - input *pbpeering.ReplicationMessage + input *pbpeerstream.ReplicationMessage wantErr error } run := func(t *testing.T, tc testCase) { - publisher := stream.NewEventPublisher(10 * time.Second) - store := newStateStore(t, publisher) - - srv := NewService( - testutil.Logger(t), - Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, &testStreamBackend{ - store: store, - pub: publisher, - }) + srv, _ := newTestServer(t, nil) client := NewMockClient(context.Background()) @@ -229,10 +201,10 @@ func TestStreamResources_Server_FirstRequest(t *testing.T) { tt := []testCase{ { name: "unexpected response", - input: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Response_{ - Response: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, + input: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Response_{ + Response: &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLService, ResourceID: "api-service", Nonce: "2", }, @@ -242,20 +214,20 @@ func TestStreamResources_Server_FirstRequest(t *testing.T) { }, { name: "missing peer id", - input: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{}, + input: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{}, }, }, wantErr: status.Error(codes.InvalidArgument, "initial subscription request must specify a PeerID"), }, { name: "unexpected nonce", - input: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - PeerID: "63b60245-c475-426b-b314-4588d210859d", - Nonce: "1", + input: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + PeerID: "63b60245-c475-426b-b314-4588d210859d", + ResponseNonce: "1", }, }, }, @@ -263,9 +235,9 @@ func TestStreamResources_Server_FirstRequest(t *testing.T) { }, { name: "unknown resource", - input: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ + input: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ PeerID: "63b60245-c475-426b-b314-4588d210859d", ResourceURL: "nomad.Job", }, @@ -275,11 +247,11 @@ func TestStreamResources_Server_FirstRequest(t *testing.T) { }, { name: "unknown peer", - input: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ + input: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ PeerID: "63b60245-c475-426b-b314-4588d210859d", - ResourceURL: pbpeering.TypeURLService, + ResourceURL: pbpeerstream.TypeURLService, }, }, }, @@ -296,34 +268,22 @@ func TestStreamResources_Server_FirstRequest(t *testing.T) { } func TestStreamResources_Server_Terminate(t *testing.T) { - publisher := stream.NewEventPublisher(10 * time.Second) - store := newStateStore(t, publisher) - - srv := NewService( - testutil.Logger(t), - Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, &testStreamBackend{ - store: store, - pub: publisher, - }) - it := incrementalTime{ base: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC), } - srv.streams.timeNow = it.Now - p := writeEstablishedPeering(t, store, 1, "my-peer") - var ( - peerID = p.ID // for Send - remotePeerID = p.PeerID // for Recv - ) + srv, store := newTestServer(t, func(c *Config) { + c.Tracker.SetClock(it.Now) + }) + + p := writePeeringToBeDialed(t, store, 1, "my-peer") + require.Empty(t, p.PeerID, "should be empty if being dialed") + peerID := p.ID // Set the initial roots and CA configuration. _, _ = writeInitialRootsAndCA(t, store) - client := makeClient(t, srv, peerID, remotePeerID) + client := makeClient(t, srv, peerID) // TODO(peering): test fails if we don't drain the stream with this call because the // server gets blocked sending the termination message. Figure out a way to let @@ -331,7 +291,7 @@ func TestStreamResources_Server_Terminate(t *testing.T) { receiveRoots, err := client.Recv() require.NoError(t, err) require.NotNil(t, receiveRoots.GetResponse()) - require.Equal(t, pbpeering.TypeURLRoots, receiveRoots.GetResponse().ResourceURL) + require.Equal(t, pbpeerstream.TypeURLRoots, receiveRoots.GetResponse().ResourceURL) testutil.RunStep(t, "new stream gets tracked", func(t *testing.T) { retry.Run(t, func(r *retry.R) { @@ -353,43 +313,31 @@ func TestStreamResources_Server_Terminate(t *testing.T) { receivedTerm, err := client.Recv() require.NoError(t, err) - expect := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Terminated_{ - Terminated: &pbpeering.ReplicationMessage_Terminated{}, + expect := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Terminated_{ + Terminated: &pbpeerstream.ReplicationMessage_Terminated{}, }, } prototest.AssertDeepEqual(t, expect, receivedTerm) } func TestStreamResources_Server_StreamTracker(t *testing.T) { - publisher := stream.NewEventPublisher(10 * time.Second) - store := newStateStore(t, publisher) - - srv := NewService( - testutil.Logger(t), - Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, &testStreamBackend{ - store: store, - pub: publisher, - }) - it := incrementalTime{ base: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC), } - srv.streams.timeNow = it.Now + + srv, store := newTestServer(t, func(c *Config) { + c.Tracker.SetClock(it.Now) + }) // Set the initial roots and CA configuration. _, rootA := writeInitialRootsAndCA(t, store) - p := writeEstablishedPeering(t, store, 1, "my-peer") - var ( - peerID = p.ID // for Send - remotePeerID = p.PeerID // for Recv - ) + p := writePeeringToBeDialed(t, store, 1, "my-peer") + require.Empty(t, p.PeerID, "should be empty if being dialed") + peerID := p.ID - client := makeClient(t, srv, peerID, remotePeerID) + client := makeClient(t, srv, peerID) testutil.RunStep(t, "new stream gets tracked", func(t *testing.T) { retry.Run(t, func(r *retry.R) { @@ -403,12 +351,12 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { var lastSendSuccess time.Time testutil.RunStep(t, "ack tracked as success", func(t *testing.T) { - ack := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - PeerID: peerID, - ResourceURL: pbpeering.TypeURLService, - Nonce: "1", + ack := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + PeerID: peerID, + ResourceURL: pbpeerstream.TypeURLService, + ResponseNonce: "1", // Acks do not have an Error populated in the request }, @@ -420,7 +368,7 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { lastSendSuccess = it.base.Add(time.Duration(sequence) * time.Second).UTC() - expect := StreamStatus{ + expect := Status{ Connected: true, LastAck: lastSendSuccess, } @@ -436,12 +384,12 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { var lastNackMsg string testutil.RunStep(t, "nack tracked as error", func(t *testing.T) { - nack := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - PeerID: peerID, - ResourceURL: pbpeering.TypeURLService, - Nonce: "2", + nack := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + PeerID: peerID, + ResourceURL: pbpeerstream.TypeURLService, + ResponseNonce: "2", Error: &pbstatus.Status{ Code: int32(code.Code_UNAVAILABLE), Message: "bad bad not good", @@ -456,7 +404,7 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { lastNackMsg = "client peer was unable to apply resource: bad bad not good" lastNack = it.base.Add(time.Duration(sequence) * time.Second).UTC() - expect := StreamStatus{ + expect := Status{ Connected: true, LastAck: lastSendSuccess, LastNack: lastNack, @@ -473,13 +421,13 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { var lastRecvSuccess time.Time testutil.RunStep(t, "response applied locally", func(t *testing.T) { - resp := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Response_{ - Response: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, + resp := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Response_{ + Response: &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLService, ResourceID: "api", Nonce: "21", - Operation: pbpeering.ReplicationMessage_Response_UPSERT, + Operation: pbpeerstream.Operation_OPERATION_UPSERT, Resource: makeAnyPB(t, &pbservice.IndexedCheckServiceNodes{}), }, }, @@ -488,16 +436,16 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { require.NoError(t, err) sequence++ - expectRoots := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Response_{ - Response: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLRoots, + expectRoots := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Response_{ + Response: &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLRoots, ResourceID: "roots", Resource: makeAnyPB(t, &pbpeering.PeeringTrustBundle{ TrustDomain: connect.TestTrustDomain, RootPEMs: []string{rootA.RootCert}, }), - Operation: pbpeering.ReplicationMessage_Response_UPSERT, + Operation: pbpeerstream.Operation_OPERATION_UPSERT, }, }, } @@ -509,11 +457,11 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { ack, err := client.Recv() require.NoError(t, err) - expectAck := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: pbpeering.TypeURLService, - Nonce: "21", + expectAck := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + ResourceURL: pbpeerstream.TypeURLService, + ResponseNonce: "21", }, }, } @@ -521,7 +469,7 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { lastRecvSuccess = it.base.Add(time.Duration(sequence) * time.Second).UTC() - expect := StreamStatus{ + expect := Status{ Connected: true, LastAck: lastSendSuccess, LastNack: lastNack, @@ -540,15 +488,15 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { var lastRecvErrorMsg string testutil.RunStep(t, "response fails to apply locally", func(t *testing.T) { - resp := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Response_{ - Response: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, + resp := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Response_{ + Response: &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLService, ResourceID: "web", Nonce: "24", // Unknown operation gets NACKed - Operation: pbpeering.ReplicationMessage_Response_Unknown, + Operation: pbpeerstream.Operation_OPERATION_UNSPECIFIED, }, }, } @@ -559,14 +507,14 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { ack, err := client.Recv() require.NoError(t, err) - expectNack := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: pbpeering.TypeURLService, - Nonce: "24", + expectNack := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + ResourceURL: pbpeerstream.TypeURLService, + ResponseNonce: "24", Error: &pbstatus.Status{ Code: int32(code.Code_INVALID_ARGUMENT), - Message: `unsupported operation: "Unknown"`, + Message: `unsupported operation: "OPERATION_UNSPECIFIED"`, }, }, }, @@ -574,9 +522,9 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { prototest.AssertDeepEqual(t, expectNack, ack) lastRecvError = it.base.Add(time.Duration(sequence) * time.Second).UTC() - lastRecvErrorMsg = `unsupported operation: "Unknown"` + lastRecvErrorMsg = `unsupported operation: "OPERATION_UNSPECIFIED"` - expect := StreamStatus{ + expect := Status{ Connected: true, LastAck: lastSendSuccess, LastNack: lastNack, @@ -602,7 +550,7 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { sequence++ disconnectTime := it.base.Add(time.Duration(sequence) * time.Second).UTC() - expect := StreamStatus{ + expect := Status{ Connected: false, LastAck: lastSendSuccess, LastNack: lastNack, @@ -622,26 +570,17 @@ func TestStreamResources_Server_StreamTracker(t *testing.T) { } func TestStreamResources_Server_ServiceUpdates(t *testing.T) { - publisher := stream.NewEventPublisher(10 * time.Second) - store := newStateStore(t, publisher) + srv, store := newTestServer(t, nil) // Create a peering var lastIdx uint64 = 1 - p := writeEstablishedPeering(t, store, lastIdx, "my-peering") + p := writePeeringToBeDialed(t, store, lastIdx, "my-peering") + require.Empty(t, p.PeerID, "should be empty if being dialed") // Set the initial roots and CA configuration. _, _ = writeInitialRootsAndCA(t, store) - srv := NewService( - testutil.Logger(t), - Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, &testStreamBackend{ - store: store, - pub: publisher, - }) - client := makeClient(t, srv, p.ID, p.PeerID) + client := makeClient(t, srv, p.ID) // Register a service that is not yet exported mysql := &structs.CheckServiceNode{ @@ -699,38 +638,38 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { require.NoError(t, store.EnsureConfigEntry(lastIdx, entry)) expectReplEvents(t, client, - func(t *testing.T, msg *pbpeering.ReplicationMessage) { - require.Equal(t, pbpeering.TypeURLRoots, msg.GetResponse().ResourceURL) + func(t *testing.T, msg *pbpeerstream.ReplicationMessage) { + require.Equal(t, pbpeerstream.TypeURLRoots, msg.GetResponse().ResourceURL) // Roots tested in TestStreamResources_Server_CARootUpdates }, - func(t *testing.T, msg *pbpeering.ReplicationMessage) { + func(t *testing.T, msg *pbpeerstream.ReplicationMessage) { // no mongo instances exist - require.Equal(t, pbpeering.TypeURLService, msg.GetResponse().ResourceURL) + require.Equal(t, pbpeerstream.TypeURLService, msg.GetResponse().ResourceURL) require.Equal(t, mongoSN, msg.GetResponse().ResourceID) - require.Equal(t, pbpeering.ReplicationMessage_Response_DELETE, msg.GetResponse().Operation) + require.Equal(t, pbpeerstream.Operation_OPERATION_DELETE, msg.GetResponse().Operation) require.Nil(t, msg.GetResponse().Resource) }, - func(t *testing.T, msg *pbpeering.ReplicationMessage) { + func(t *testing.T, msg *pbpeerstream.ReplicationMessage) { // proxies can't export because no mesh gateway exists yet - require.Equal(t, pbpeering.TypeURLService, msg.GetResponse().ResourceURL) + require.Equal(t, pbpeerstream.TypeURLService, msg.GetResponse().ResourceURL) require.Equal(t, mongoProxySN, msg.GetResponse().ResourceID) - require.Equal(t, pbpeering.ReplicationMessage_Response_DELETE, msg.GetResponse().Operation) + require.Equal(t, pbpeerstream.Operation_OPERATION_DELETE, msg.GetResponse().Operation) require.Nil(t, msg.GetResponse().Resource) }, - func(t *testing.T, msg *pbpeering.ReplicationMessage) { - require.Equal(t, pbpeering.TypeURLService, msg.GetResponse().ResourceURL) + func(t *testing.T, msg *pbpeerstream.ReplicationMessage) { + require.Equal(t, pbpeerstream.TypeURLService, msg.GetResponse().ResourceURL) require.Equal(t, mysqlSN, msg.GetResponse().ResourceID) - require.Equal(t, pbpeering.ReplicationMessage_Response_UPSERT, msg.GetResponse().Operation) + require.Equal(t, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) var nodes pbservice.IndexedCheckServiceNodes require.NoError(t, ptypes.UnmarshalAny(msg.GetResponse().Resource, &nodes)) require.Len(t, nodes.Nodes, 1) }, - func(t *testing.T, msg *pbpeering.ReplicationMessage) { + func(t *testing.T, msg *pbpeerstream.ReplicationMessage) { // proxies can't export because no mesh gateway exists yet - require.Equal(t, pbpeering.TypeURLService, msg.GetResponse().ResourceURL) + require.Equal(t, pbpeerstream.TypeURLService, msg.GetResponse().ResourceURL) require.Equal(t, mysqlProxySN, msg.GetResponse().ResourceID) - require.Equal(t, pbpeering.ReplicationMessage_Response_DELETE, msg.GetResponse().Operation) + require.Equal(t, pbpeerstream.Operation_OPERATION_DELETE, msg.GetResponse().Operation) require.Nil(t, msg.GetResponse().Resource) }, ) @@ -749,10 +688,10 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { require.NoError(t, store.EnsureService(lastIdx, "mgw", gateway.Service)) expectReplEvents(t, client, - func(t *testing.T, msg *pbpeering.ReplicationMessage) { - require.Equal(t, pbpeering.TypeURLService, msg.GetResponse().ResourceURL) + func(t *testing.T, msg *pbpeerstream.ReplicationMessage) { + require.Equal(t, pbpeerstream.TypeURLService, msg.GetResponse().ResourceURL) require.Equal(t, mongoProxySN, msg.GetResponse().ResourceID) - require.Equal(t, pbpeering.ReplicationMessage_Response_UPSERT, msg.GetResponse().Operation) + require.Equal(t, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) var nodes pbservice.IndexedCheckServiceNodes require.NoError(t, ptypes.UnmarshalAny(msg.GetResponse().Resource, &nodes)) @@ -766,10 +705,10 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { } require.Equal(t, spiffeIDs, pm.SpiffeID) }, - func(t *testing.T, msg *pbpeering.ReplicationMessage) { - require.Equal(t, pbpeering.TypeURLService, msg.GetResponse().ResourceURL) + func(t *testing.T, msg *pbpeerstream.ReplicationMessage) { + require.Equal(t, pbpeerstream.TypeURLService, msg.GetResponse().ResourceURL) require.Equal(t, mysqlProxySN, msg.GetResponse().ResourceID) - require.Equal(t, pbpeering.ReplicationMessage_Response_UPSERT, msg.GetResponse().Operation) + require.Equal(t, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) var nodes pbservice.IndexedCheckServiceNodes require.NoError(t, ptypes.UnmarshalAny(msg.GetResponse().Resource, &nodes)) @@ -779,6 +718,7 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { require.Equal(t, "tcp", pm.Protocol) spiffeIDs := []string{ "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/mysql", + "spiffe://11111111-2222-3333-4444-555555555555.consul/gateway/mesh/dc/dc1", } require.Equal(t, spiffeIDs, pm.SpiffeID) }, @@ -800,7 +740,7 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { retry.Run(t, func(r *retry.R) { msg, err := client.RecvWithTimeout(100 * time.Millisecond) require.NoError(r, err) - require.Equal(r, pbpeering.ReplicationMessage_Response_UPSERT, msg.GetResponse().Operation) + require.Equal(r, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) require.Equal(r, mongo.Service.CompoundServiceName().String(), msg.GetResponse().ResourceID) var nodes pbservice.IndexedCheckServiceNodes @@ -832,7 +772,7 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { retry.Run(t, func(r *retry.R) { msg, err := client.RecvWithTimeout(100 * time.Millisecond) require.NoError(r, err) - require.Equal(r, pbpeering.ReplicationMessage_Response_DELETE, msg.GetResponse().Operation) + require.Equal(r, pbpeerstream.Operation_OPERATION_DELETE, msg.GetResponse().Operation) require.Equal(r, mysql.Service.CompoundServiceName().String(), msg.GetResponse().ResourceID) require.Nil(r, msg.GetResponse().Resource) }) @@ -846,7 +786,7 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { retry.Run(t, func(r *retry.R) { msg, err := client.RecvWithTimeout(100 * time.Millisecond) require.NoError(r, err) - require.Equal(r, pbpeering.ReplicationMessage_Response_DELETE, msg.GetResponse().Operation) + require.Equal(r, pbpeerstream.Operation_OPERATION_DELETE, msg.GetResponse().Operation) require.Equal(r, mongo.Service.CompoundServiceName().String(), msg.GetResponse().ResourceID) require.Nil(r, msg.GetResponse().Resource) }) @@ -854,35 +794,24 @@ func TestStreamResources_Server_ServiceUpdates(t *testing.T) { } func TestStreamResources_Server_CARootUpdates(t *testing.T) { - publisher := stream.NewEventPublisher(10 * time.Second) - - store := newStateStore(t, publisher) + srv, store := newTestServer(t, nil) // Create a peering var lastIdx uint64 = 1 - p := writeEstablishedPeering(t, store, lastIdx, "my-peering") - - srv := NewService( - testutil.Logger(t), - Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, &testStreamBackend{ - store: store, - pub: publisher, - }) + p := writePeeringToBeDialed(t, store, lastIdx, "my-peering") + require.Empty(t, p.PeerID, "should be empty if being dialed") // Set the initial roots and CA configuration. clusterID, rootA := writeInitialRootsAndCA(t, store) - client := makeClient(t, srv, p.ID, p.PeerID) + client := makeClient(t, srv, p.ID) testutil.RunStep(t, "initial CA Roots replication", func(t *testing.T) { expectReplEvents(t, client, - func(t *testing.T, msg *pbpeering.ReplicationMessage) { - require.Equal(t, pbpeering.TypeURLRoots, msg.GetResponse().ResourceURL) + func(t *testing.T, msg *pbpeerstream.ReplicationMessage) { + require.Equal(t, pbpeerstream.TypeURLRoots, msg.GetResponse().ResourceURL) require.Equal(t, "roots", msg.GetResponse().ResourceID) - require.Equal(t, pbpeering.ReplicationMessage_Response_UPSERT, msg.GetResponse().Operation) + require.Equal(t, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) var trustBundle pbpeering.PeeringTrustBundle require.NoError(t, ptypes.UnmarshalAny(msg.GetResponse().Resource, &trustBundle)) @@ -908,10 +837,10 @@ func TestStreamResources_Server_CARootUpdates(t *testing.T) { require.NoError(t, err) expectReplEvents(t, client, - func(t *testing.T, msg *pbpeering.ReplicationMessage) { - require.Equal(t, pbpeering.TypeURLRoots, msg.GetResponse().ResourceURL) + func(t *testing.T, msg *pbpeerstream.ReplicationMessage) { + require.Equal(t, pbpeerstream.TypeURLRoots, msg.GetResponse().ResourceURL) require.Equal(t, "roots", msg.GetResponse().ResourceID) - require.Equal(t, pbpeering.ReplicationMessage_Response_UPSERT, msg.GetResponse().Operation) + require.Equal(t, pbpeerstream.Operation_OPERATION_UPSERT, msg.GetResponse().Operation) var trustBundle pbpeering.PeeringTrustBundle require.NoError(t, ptypes.UnmarshalAny(msg.GetResponse().Resource, &trustBundle)) @@ -926,12 +855,7 @@ func TestStreamResources_Server_CARootUpdates(t *testing.T) { // makeClient sets up a *MockClient with the initial subscription // message handshake. -func makeClient( - t *testing.T, - srv pbpeering.PeeringServiceServer, - peerID string, - remotePeerID string, -) *MockClient { +func makeClient(t *testing.T, srv pbpeerstream.PeerStreamServiceServer, peerID string) *MockClient { t.Helper() client := NewMockClient(context.Background()) @@ -948,11 +872,11 @@ func makeClient( }() // Issue a services subscription to server - init := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ + init := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ PeerID: peerID, - ResourceURL: pbpeering.TypeURLService, + ResourceURL: pbpeerstream.TypeURLService, }, }, } @@ -962,11 +886,14 @@ func makeClient( receivedSub, err := client.Recv() require.NoError(t, err) - expect := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: pbpeering.TypeURLService, - PeerID: remotePeerID, + expect := &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + ResourceURL: pbpeerstream.TypeURLService, + // The PeerID field is only set for the messages coming FROM + // the establishing side and are going to be empty from the + // other side. + PeerID: "", }, }, } @@ -976,30 +903,15 @@ func makeClient( } type testStreamBackend struct { - pub state.EventPublisher - store *state.Store - applier *testApplier - leader func() bool - leaderAddress *leaderAddress + pub state.EventPublisher + store *state.Store + leader func() bool + + leaderAddrLock sync.Mutex + leaderAddr string } -var _ LeaderAddress = (*leaderAddress)(nil) - -type leaderAddress struct { - addr string -} - -func (l *leaderAddress) Set(addr string) { - // noop -} - -func (l *leaderAddress) Get() string { - return l.addr -} - -func (b *testStreamBackend) LeaderAddress() LeaderAddress { - return b.leaderAddress -} +var _ Backend = (*testStreamBackend)(nil) func (b *testStreamBackend) IsLeader() bool { if b.leader != nil { @@ -1008,91 +920,47 @@ func (b *testStreamBackend) IsLeader() bool { return true } +func (b *testStreamBackend) SetLeaderAddress(addr string) { + b.leaderAddrLock.Lock() + defer b.leaderAddrLock.Unlock() + b.leaderAddr = addr +} + +func (b *testStreamBackend) GetLeaderAddress() string { + b.leaderAddrLock.Lock() + defer b.leaderAddrLock.Unlock() + return b.leaderAddr +} + func (b *testStreamBackend) Subscribe(req *stream.SubscribeRequest) (*stream.Subscription, error) { return b.pub.Subscribe(req) } -func (b *testStreamBackend) Store() Store { - return b.store -} - -func (b *testStreamBackend) Forward(info structs.RPCInfo, f func(conn *grpc.ClientConn) error) (handled bool, err error) { - return true, nil -} - -func (b *testStreamBackend) GetAgentCACertificates() ([]string, error) { - return []string{}, nil -} - -func (b *testStreamBackend) GetServerAddresses() ([]string, error) { - return []string{}, nil -} - -func (b *testStreamBackend) GetServerName() string { - return "" -} - -func (b *testStreamBackend) EncodeToken(tok *structs.PeeringToken) ([]byte, error) { - return nil, nil -} - -func (b *testStreamBackend) DecodeToken([]byte) (*structs.PeeringToken, error) { - return nil, nil -} - -func (b *testStreamBackend) EnterpriseCheckPartitions(_ string) error { - return nil -} - -func (b *testStreamBackend) EnterpriseCheckNamespaces(_ string) error { - return nil -} - -func (b *testStreamBackend) Apply() Apply { - return b.applier -} - -type testApplier struct { - store *state.Store -} - -func (a *testApplier) CheckPeeringUUID(id string) (bool, error) { +func (b *testStreamBackend) PeeringTerminateByID(req *pbpeering.PeeringTerminateByIDRequest) error { panic("not implemented") } -func (a *testApplier) PeeringWrite(req *pbpeering.PeeringWriteRequest) error { - panic("not implemented") -} - -func (a *testApplier) PeeringDelete(req *pbpeering.PeeringDeleteRequest) error { - panic("not implemented") -} - -func (a *testApplier) PeeringTerminateByID(req *pbpeering.PeeringTerminateByIDRequest) error { - panic("not implemented") -} - -func (a *testApplier) PeeringTrustBundleWrite(req *pbpeering.PeeringTrustBundleWriteRequest) error { +func (b *testStreamBackend) PeeringTrustBundleWrite(req *pbpeering.PeeringTrustBundleWriteRequest) error { panic("not implemented") } // CatalogRegister mocks catalog registrations through Raft by copying the logic of FSM.applyRegister. -func (a *testApplier) CatalogRegister(req *structs.RegisterRequest) error { - return a.store.EnsureRegistration(1, req) +func (b *testStreamBackend) CatalogRegister(req *structs.RegisterRequest) error { + return b.store.EnsureRegistration(1, req) } // CatalogDeregister mocks catalog de-registrations through Raft by copying the logic of FSM.applyDeregister. -func (a *testApplier) CatalogDeregister(req *structs.DeregisterRequest) error { +func (b *testStreamBackend) CatalogDeregister(req *structs.DeregisterRequest) error { if req.ServiceID != "" { - if err := a.store.DeleteService(1, req.Node, req.ServiceID, &req.EnterpriseMeta, req.PeerName); err != nil { + if err := b.store.DeleteService(1, req.Node, req.ServiceID, &req.EnterpriseMeta, req.PeerName); err != nil { return err } } else if req.CheckID != "" { - if err := a.store.DeleteCheck(1, req.Node, req.CheckID, &req.EnterpriseMeta, req.PeerName); err != nil { + if err := b.store.DeleteCheck(1, req.Node, req.CheckID, &req.EnterpriseMeta, req.PeerName); err != nil { return err } } else { - if err := a.store.DeleteNode(1, req.Node, &req.EnterpriseMeta, req.PeerName); err != nil { + if err := b.store.DeleteNode(1, req.Node, &req.EnterpriseMeta, req.PeerName); err != nil { return err } } @@ -1102,23 +970,12 @@ func (a *testApplier) CatalogDeregister(req *structs.DeregisterRequest) error { func Test_processResponse_Validation(t *testing.T) { type testCase struct { name string - in *pbpeering.ReplicationMessage_Response - expect *pbpeering.ReplicationMessage + in *pbpeerstream.ReplicationMessage_Response + expect *pbpeerstream.ReplicationMessage wantErr bool } - publisher := stream.NewEventPublisher(10 * time.Second) - store := newStateStore(t, publisher) - - srv := NewService( - testutil.Logger(t), - Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, &testStreamBackend{ - store: store, - pub: publisher, - }) + srv, _ := newTestServer(t, nil) run := func(t *testing.T, tc testCase) { reply, err := srv.processResponse("", "", tc.in) @@ -1133,18 +990,18 @@ func Test_processResponse_Validation(t *testing.T) { tt := []testCase{ { name: "valid upsert", - in: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, + in: &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLService, ResourceID: "api", Nonce: "1", - Operation: pbpeering.ReplicationMessage_Response_UPSERT, + Operation: pbpeerstream.Operation_OPERATION_UPSERT, Resource: makeAnyPB(t, &pbservice.IndexedCheckServiceNodes{}), }, - expect: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: pbpeering.TypeURLService, - Nonce: "1", + expect: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + ResourceURL: pbpeerstream.TypeURLService, + ResponseNonce: "1", }, }, }, @@ -1152,17 +1009,17 @@ func Test_processResponse_Validation(t *testing.T) { }, { name: "valid delete", - in: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, + in: &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLService, ResourceID: "api", Nonce: "1", - Operation: pbpeering.ReplicationMessage_Response_DELETE, + Operation: pbpeerstream.Operation_OPERATION_DELETE, }, - expect: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: pbpeering.TypeURLService, - Nonce: "1", + expect: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + ResourceURL: pbpeerstream.TypeURLService, + ResponseNonce: "1", }, }, }, @@ -1170,16 +1027,16 @@ func Test_processResponse_Validation(t *testing.T) { }, { name: "invalid resource url", - in: &pbpeering.ReplicationMessage_Response{ + in: &pbpeerstream.ReplicationMessage_Response{ ResourceURL: "nomad.Job", Nonce: "1", - Operation: pbpeering.ReplicationMessage_Response_Unknown, + Operation: pbpeerstream.Operation_OPERATION_UNSPECIFIED, }, - expect: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: "nomad.Job", - Nonce: "1", + expect: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + ResourceURL: "nomad.Job", + ResponseNonce: "1", Error: &pbstatus.Status{ Code: int32(code.Code_INVALID_ARGUMENT), Message: `received response for unknown resource type "nomad.Job"`, @@ -1191,19 +1048,19 @@ func Test_processResponse_Validation(t *testing.T) { }, { name: "unknown operation", - in: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, + in: &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLService, Nonce: "1", - Operation: pbpeering.ReplicationMessage_Response_Unknown, + Operation: pbpeerstream.Operation_OPERATION_UNSPECIFIED, }, - expect: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: pbpeering.TypeURLService, - Nonce: "1", + expect: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + ResourceURL: pbpeerstream.TypeURLService, + ResponseNonce: "1", Error: &pbstatus.Status{ Code: int32(code.Code_INVALID_ARGUMENT), - Message: `unsupported operation: "Unknown"`, + Message: `unsupported operation: "OPERATION_UNSPECIFIED"`, }, }, }, @@ -1212,16 +1069,16 @@ func Test_processResponse_Validation(t *testing.T) { }, { name: "out of range operation", - in: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, + in: &pbpeerstream.ReplicationMessage_Response{ + ResourceURL: pbpeerstream.TypeURLService, Nonce: "1", - Operation: pbpeering.ReplicationMessage_Response_Operation(100000), + Operation: pbpeerstream.Operation(100000), }, - expect: &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: pbpeering.TypeURLService, - Nonce: "1", + expect: &pbpeerstream.ReplicationMessage{ + Payload: &pbpeerstream.ReplicationMessage_Request_{ + Request: &pbpeerstream.ReplicationMessage_Request{ + ResourceURL: pbpeerstream.TypeURLService, + ResponseNonce: "1", Error: &pbstatus.Status{ Code: int32(code.Code_INVALID_ARGUMENT), Message: `unsupported operation: 100000`, @@ -1239,12 +1096,21 @@ func Test_processResponse_Validation(t *testing.T) { } } -// writeEstablishedPeering creates a peering with the provided name and ensures +// writePeeringToDialFrom creates a peering with the provided name and ensures // the PeerID field is set for the ID of the remote peer. -func writeEstablishedPeering(t *testing.T, store *state.Store, idx uint64, peerName string) *pbpeering.Peering { +func writePeeringToDialFrom(t *testing.T, store *state.Store, idx uint64, peerName string) *pbpeering.Peering { remotePeerID, err := uuid.GenerateUUID() require.NoError(t, err) + return writeTestPeering(t, store, idx, peerName, remotePeerID) +} +// writePeeringToBeDialed creates a peering with the provided name and ensures +// the PeerID field is NOT set for the ID of the remote peer. +func writePeeringToBeDialed(t *testing.T, store *state.Store, idx uint64, peerName string) *pbpeering.Peering { + return writeTestPeering(t, store, idx, peerName, "") +} + +func writeTestPeering(t *testing.T, store *state.Store, idx uint64, peerName, remotePeerID string) *pbpeering.Peering { peering := pbpeering.Peering{ ID: testUUID(t), Name: peerName, @@ -1277,7 +1143,7 @@ func makeAnyPB(t *testing.T, pb proto.Message) *any.Any { return any } -func expectReplEvents(t *testing.T, client *MockClient, checkFns ...func(t *testing.T, got *pbpeering.ReplicationMessage)) { +func expectReplEvents(t *testing.T, client *MockClient, checkFns ...func(t *testing.T, got *pbpeerstream.ReplicationMessage)) { t.Helper() num := len(checkFns) @@ -1296,7 +1162,7 @@ func expectReplEvents(t *testing.T, client *MockClient, checkFns ...func(t *test const timeout = 10 * time.Second - var out []*pbpeering.ReplicationMessage + var out []*pbpeerstream.ReplicationMessage for len(out) < num { msg, err := client.RecvWithTimeout(timeout) if err == io.EOF && msg == nil { @@ -1322,14 +1188,14 @@ func expectReplEvents(t *testing.T, client *MockClient, checkFns ...func(t *test } switch a.GetPayload().(type) { - case *pbpeering.ReplicationMessage_Request_: + case *pbpeerstream.ReplicationMessage_Request_: reqA, reqB := a.GetRequest(), b.GetRequest() if reqA.ResourceURL != reqB.ResourceURL { return reqA.ResourceURL < reqB.ResourceURL } - return reqA.Nonce < reqB.Nonce + return reqA.ResponseNonce < reqB.ResponseNonce - case *pbpeering.ReplicationMessage_Response_: + case *pbpeerstream.ReplicationMessage_Response_: respA, respB := a.GetResponse(), b.GetResponse() if respA.ResourceURL != respB.ResourceURL { return respA.ResourceURL < respB.ResourceURL @@ -1339,7 +1205,7 @@ func expectReplEvents(t *testing.T, client *MockClient, checkFns ...func(t *test } return respA.Nonce < respB.Nonce - case *pbpeering.ReplicationMessage_Terminated_: + case *pbpeerstream.ReplicationMessage_Terminated_: return false default: @@ -1353,24 +1219,12 @@ func expectReplEvents(t *testing.T, client *MockClient, checkFns ...func(t *test } func TestHandleUpdateService(t *testing.T) { - publisher := stream.NewEventPublisher(10 * time.Second) - store := newStateStore(t, publisher) - - srv := NewService( - testutil.Logger(t), - Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, - &testStreamBackend{ - store: store, - applier: &testApplier{store: store}, - pub: publisher, - leader: func() bool { - return false - }, - }, - ) + srv, _ := newTestServer(t, func(c *Config) { + backend := c.Backend.(*testStreamBackend) + backend.leader = func() bool { + return false + } + }) type testCase struct { name string @@ -1390,7 +1244,7 @@ func TestHandleUpdateService(t *testing.T) { run := func(t *testing.T, tc testCase) { // Seed the local catalog with some data to reconcile against. for _, reg := range tc.seed { - require.NoError(t, srv.Backend.Apply().CatalogRegister(reg)) + require.NoError(t, srv.Backend.CatalogRegister(reg)) } // Simulate an update arriving for billing/api. @@ -1398,7 +1252,7 @@ func TestHandleUpdateService(t *testing.T) { for svc, expect := range tc.expect { t.Run(svc, func(t *testing.T) { - _, got, err := srv.Backend.Store().CheckServiceNodes(nil, svc, &defaultMeta, peerName) + _, got, err := srv.GetStore().CheckServiceNodes(nil, svc, &defaultMeta, peerName) require.NoError(t, err) requireEqualInstances(t, expect, got) }) @@ -2202,8 +2056,59 @@ func requireEqualInstances(t *testing.T, expect, got structs.CheckServiceNodes) } } +type testServer struct { + *Server +} + +func newTestServer(t *testing.T, configFn func(c *Config)) (*testServer, *state.Store) { + publisher := stream.NewEventPublisher(10 * time.Second) + store := newStateStore(t, publisher) + + ports := freeport.GetN(t, 1) // {grpc} + + cfg := Config{ + Backend: &testStreamBackend{ + store: store, + pub: publisher, + }, + Tracker: NewTracker(), + GetStore: func() StateStore { return store }, + Logger: testutil.Logger(t), + ACLResolver: nil, // TODO(peering): add something for acl testing + Datacenter: "dc1", + ConnectEnabled: true, + } + if configFn != nil { + configFn(&cfg) + } + + grpcServer := grpc.NewServer() + + srv := NewServer(cfg) + srv.Register(grpcServer) + + var ( + grpcPort = ports[0] + grpcAddr = fmt.Sprintf("127.0.0.1:%d", grpcPort) + ) + ln, err := net.Listen("tcp", grpcAddr) + require.NoError(t, err) + go func() { + _ = grpcServer.Serve(ln) + }() + t.Cleanup(grpcServer.Stop) + + return &testServer{ + Server: srv, + }, store +} + func testUUID(t *testing.T) string { v, err := lib.GenerateUUID(nil) require.NoError(t, err) return v } + +func noopForwardRPC(structs.RPCInfo, func(*grpc.ClientConn) error) (bool, error) { + return false, nil +} diff --git a/agent/rpc/peering/stream_tracker.go b/agent/grpc-external/services/peerstream/stream_tracker.go similarity index 66% rename from agent/rpc/peering/stream_tracker.go rename to agent/grpc-external/services/peerstream/stream_tracker.go index af2cbe1c28..5ec0f7ebf7 100644 --- a/agent/rpc/peering/stream_tracker.go +++ b/agent/grpc-external/services/peerstream/stream_tracker.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "fmt" @@ -6,86 +6,94 @@ import ( "time" ) -// streamTracker contains a map of (PeerID -> StreamStatus). +// Tracker contains a map of (PeerID -> Status). // As streams are opened and closed we track details about their status. -type streamTracker struct { +type Tracker struct { mu sync.RWMutex - streams map[string]*lockableStreamStatus + streams map[string]*MutableStatus // timeNow is a shim for testing. timeNow func() time.Time } -func newStreamTracker() *streamTracker { - return &streamTracker{ - streams: make(map[string]*lockableStreamStatus), +func NewTracker() *Tracker { + return &Tracker{ + streams: make(map[string]*MutableStatus), timeNow: time.Now, } } -// connected registers a stream for a given peer, and marks it as connected. +func (t *Tracker) SetClock(clock func() time.Time) { + if clock == nil { + t.timeNow = time.Now + } else { + t.timeNow = clock + } +} + +// Connected registers a stream for a given peer, and marks it as connected. // It also enforces that there is only one active stream for a peer. -func (t *streamTracker) connected(id string) (*lockableStreamStatus, error) { +func (t *Tracker) Connected(id string) (*MutableStatus, error) { t.mu.Lock() defer t.mu.Unlock() status, ok := t.streams[id] if !ok { - status = newLockableStreamStatus(t.timeNow) + status = newMutableStatus(t.timeNow) t.streams[id] = status return status, nil } - if status.connected() { + if status.IsConnected() { return nil, fmt.Errorf("there is an active stream for the given PeerID %q", id) } - status.trackConnected() + status.TrackConnected() return status, nil } -// disconnected ensures that if a peer id's stream status is tracked, it is marked as disconnected. -func (t *streamTracker) disconnected(id string) { +// Disconnected ensures that if a peer id's stream status is tracked, it is marked as disconnected. +func (t *Tracker) Disconnected(id string) { t.mu.Lock() defer t.mu.Unlock() if status, ok := t.streams[id]; ok { - status.trackDisconnected() + status.TrackDisconnected() } } -func (t *streamTracker) streamStatus(id string) (resp StreamStatus, found bool) { +func (t *Tracker) StreamStatus(id string) (resp Status, found bool) { t.mu.RLock() defer t.mu.RUnlock() s, ok := t.streams[id] if !ok { - return StreamStatus{}, false + return Status{}, false } - return s.status(), true + return s.GetStatus(), true } -func (t *streamTracker) connectedStreams() map[string]chan struct{} { +func (t *Tracker) ConnectedStreams() map[string]chan struct{} { t.mu.RLock() defer t.mu.RUnlock() resp := make(map[string]chan struct{}) for peer, status := range t.streams { - if status.connected() { + if status.IsConnected() { resp[peer] = status.doneCh } } return resp } -func (t *streamTracker) deleteStatus(id string) { +func (t *Tracker) DeleteStatus(id string) { t.mu.Lock() defer t.mu.Unlock() delete(t.streams, id) } -type lockableStreamStatus struct { +type MutableStatus struct { mu sync.RWMutex // timeNow is a shim for testing. @@ -95,12 +103,12 @@ type lockableStreamStatus struct { // to the peer before the stream's context is cancelled. doneCh chan struct{} - StreamStatus + Status } -// StreamStatus contains information about the replication stream to a peer cluster. +// Status contains information about the replication stream to a peer cluster. // TODO(peering): There's a lot of fields here... -type StreamStatus struct { +type Status struct { // Connected is true when there is an open stream for the peer. Connected bool @@ -136,9 +144,9 @@ type StreamStatus struct { LastReceiveErrorMessage string } -func newLockableStreamStatus(now func() time.Time) *lockableStreamStatus { - return &lockableStreamStatus{ - StreamStatus: StreamStatus{ +func newMutableStatus(now func() time.Time) *MutableStatus { + return &MutableStatus{ + Status: Status{ Connected: true, }, timeNow: now, @@ -146,54 +154,58 @@ func newLockableStreamStatus(now func() time.Time) *lockableStreamStatus { } } -func (s *lockableStreamStatus) trackAck() { +func (s *MutableStatus) Done() <-chan struct{} { + return s.doneCh +} + +func (s *MutableStatus) TrackAck() { s.mu.Lock() s.LastAck = s.timeNow().UTC() s.mu.Unlock() } -func (s *lockableStreamStatus) trackSendError(error string) { +func (s *MutableStatus) TrackSendError(error string) { s.mu.Lock() s.LastSendError = s.timeNow().UTC() s.LastSendErrorMessage = error s.mu.Unlock() } -func (s *lockableStreamStatus) trackReceiveSuccess() { +func (s *MutableStatus) TrackReceiveSuccess() { s.mu.Lock() s.LastReceiveSuccess = s.timeNow().UTC() s.mu.Unlock() } -func (s *lockableStreamStatus) trackReceiveError(error string) { +func (s *MutableStatus) TrackReceiveError(error string) { s.mu.Lock() s.LastReceiveError = s.timeNow().UTC() s.LastReceiveErrorMessage = error s.mu.Unlock() } -func (s *lockableStreamStatus) trackNack(msg string) { +func (s *MutableStatus) TrackNack(msg string) { s.mu.Lock() s.LastNack = s.timeNow().UTC() s.LastNackMessage = msg s.mu.Unlock() } -func (s *lockableStreamStatus) trackConnected() { +func (s *MutableStatus) TrackConnected() { s.mu.Lock() s.Connected = true s.DisconnectTime = time.Time{} s.mu.Unlock() } -func (s *lockableStreamStatus) trackDisconnected() { +func (s *MutableStatus) TrackDisconnected() { s.mu.Lock() s.Connected = false s.DisconnectTime = s.timeNow().UTC() s.mu.Unlock() } -func (s *lockableStreamStatus) connected() bool { +func (s *MutableStatus) IsConnected() bool { var resp bool s.mu.RLock() @@ -203,9 +215,9 @@ func (s *lockableStreamStatus) connected() bool { return resp } -func (s *lockableStreamStatus) status() StreamStatus { +func (s *MutableStatus) GetStatus() Status { s.mu.RLock() - copy := s.StreamStatus + copy := s.Status s.mu.RUnlock() return copy diff --git a/agent/rpc/peering/stream_tracker_test.go b/agent/grpc-external/services/peerstream/stream_tracker_test.go similarity index 68% rename from agent/rpc/peering/stream_tracker_test.go rename to agent/grpc-external/services/peerstream/stream_tracker_test.go index d6b49ef917..a698ccc6f4 100644 --- a/agent/rpc/peering/stream_tracker_test.go +++ b/agent/grpc-external/services/peerstream/stream_tracker_test.go @@ -1,16 +1,17 @@ -package peering +package peerstream import ( "sort" "testing" "time" - "github.com/hashicorp/consul/sdk/testutil" "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/sdk/testutil" ) -func TestStreamTracker_EnsureConnectedDisconnected(t *testing.T) { - tracker := newStreamTracker() +func TestTracker_EnsureConnectedDisconnected(t *testing.T) { + tracker := NewTracker() peerID := "63b60245-c475-426b-b314-4588d210859d" it := incrementalTime{ @@ -19,25 +20,25 @@ func TestStreamTracker_EnsureConnectedDisconnected(t *testing.T) { tracker.timeNow = it.Now var ( - statusPtr *lockableStreamStatus + statusPtr *MutableStatus err error ) testutil.RunStep(t, "new stream", func(t *testing.T) { - statusPtr, err = tracker.connected(peerID) + statusPtr, err = tracker.Connected(peerID) require.NoError(t, err) - expect := StreamStatus{ + expect := Status{ Connected: true, } - status, ok := tracker.streamStatus(peerID) + status, ok := tracker.StreamStatus(peerID) require.True(t, ok) require.Equal(t, expect, status) }) testutil.RunStep(t, "duplicate gets rejected", func(t *testing.T) { - _, err := tracker.connected(peerID) + _, err := tracker.Connected(peerID) require.Error(t, err) require.Contains(t, err.Error(), `there is an active stream for the given PeerID "63b60245-c475-426b-b314-4588d210859d"`) }) @@ -46,14 +47,14 @@ func TestStreamTracker_EnsureConnectedDisconnected(t *testing.T) { var lastSuccess time.Time testutil.RunStep(t, "stream updated", func(t *testing.T) { - statusPtr.trackAck() + statusPtr.TrackAck() sequence++ - status, ok := tracker.streamStatus(peerID) + status, ok := tracker.StreamStatus(peerID) require.True(t, ok) lastSuccess = it.base.Add(time.Duration(sequence) * time.Second).UTC() - expect := StreamStatus{ + expect := Status{ Connected: true, LastAck: lastSuccess, } @@ -61,58 +62,58 @@ func TestStreamTracker_EnsureConnectedDisconnected(t *testing.T) { }) testutil.RunStep(t, "disconnect", func(t *testing.T) { - tracker.disconnected(peerID) + tracker.Disconnected(peerID) sequence++ - expect := StreamStatus{ + expect := Status{ Connected: false, DisconnectTime: it.base.Add(time.Duration(sequence) * time.Second).UTC(), LastAck: lastSuccess, } - status, ok := tracker.streamStatus(peerID) + status, ok := tracker.StreamStatus(peerID) require.True(t, ok) require.Equal(t, expect, status) }) testutil.RunStep(t, "re-connect", func(t *testing.T) { - _, err := tracker.connected(peerID) + _, err := tracker.Connected(peerID) require.NoError(t, err) - expect := StreamStatus{ + expect := Status{ Connected: true, LastAck: lastSuccess, // DisconnectTime gets cleared on re-connect. } - status, ok := tracker.streamStatus(peerID) + status, ok := tracker.StreamStatus(peerID) require.True(t, ok) require.Equal(t, expect, status) }) testutil.RunStep(t, "delete", func(t *testing.T) { - tracker.deleteStatus(peerID) + tracker.DeleteStatus(peerID) - status, ok := tracker.streamStatus(peerID) + status, ok := tracker.StreamStatus(peerID) require.False(t, ok) require.Zero(t, status) }) } -func TestStreamTracker_connectedStreams(t *testing.T) { +func TestTracker_connectedStreams(t *testing.T) { type testCase struct { name string - setup func(t *testing.T, s *streamTracker) + setup func(t *testing.T, s *Tracker) expect []string } run := func(t *testing.T, tc testCase) { - tracker := newStreamTracker() + tracker := NewTracker() if tc.setup != nil { tc.setup(t, tracker) } - streams := tracker.connectedStreams() + streams := tracker.ConnectedStreams() var keys []string for key := range streams { @@ -130,25 +131,25 @@ func TestStreamTracker_connectedStreams(t *testing.T) { }, { name: "all streams active", - setup: func(t *testing.T, s *streamTracker) { - _, err := s.connected("foo") + setup: func(t *testing.T, s *Tracker) { + _, err := s.Connected("foo") require.NoError(t, err) - _, err = s.connected("bar") + _, err = s.Connected("bar") require.NoError(t, err) }, expect: []string{"bar", "foo"}, }, { name: "mixed active and inactive", - setup: func(t *testing.T, s *streamTracker) { - status, err := s.connected("foo") + setup: func(t *testing.T, s *Tracker) { + status, err := s.Connected("foo") require.NoError(t, err) // Mark foo as disconnected to avoid showing it as an active stream - status.trackDisconnected() + status.TrackDisconnected() - _, err = s.connected("bar") + _, err = s.Connected("bar") require.NoError(t, err) }, expect: []string{"bar"}, diff --git a/agent/rpc/peering/subscription_blocking.go b/agent/grpc-external/services/peerstream/subscription_blocking.go similarity index 91% rename from agent/rpc/peering/subscription_blocking.go rename to agent/grpc-external/services/peerstream/subscription_blocking.go index c8f771e8b8..c2720dcdbb 100644 --- a/agent/rpc/peering/subscription_blocking.go +++ b/agent/grpc-external/services/peerstream/subscription_blocking.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "context" @@ -21,7 +21,7 @@ import ( func (m *subscriptionManager) notifyExportedServicesForPeerID(ctx context.Context, state *subscriptionState, peerID string) { // syncSubscriptionsAndBlock ensures that the subscriptions to the subscription backend // match the list of services exported to the peer. - m.syncViaBlockingQuery(ctx, "exported-services", func(ctx context.Context, store Store, ws memdb.WatchSet) (interface{}, error) { + m.syncViaBlockingQuery(ctx, "exported-services", func(ctx context.Context, store StateStore, ws memdb.WatchSet) (interface{}, error) { // Get exported services for peer id _, list, err := store.ExportedServicesForPeer(ws, peerID, m.config.Datacenter) if err != nil { @@ -34,7 +34,7 @@ func (m *subscriptionManager) notifyExportedServicesForPeerID(ctx context.Contex // TODO: add a new streaming subscription type to list-by-kind-and-partition since we're getting evictions func (m *subscriptionManager) notifyMeshGatewaysForPartition(ctx context.Context, state *subscriptionState, partition string) { - m.syncViaBlockingQuery(ctx, "mesh-gateways", func(ctx context.Context, store Store, ws memdb.WatchSet) (interface{}, error) { + m.syncViaBlockingQuery(ctx, "mesh-gateways", func(ctx context.Context, store StateStore, ws memdb.WatchSet) (interface{}, error) { // Fetch our current list of all mesh gateways. entMeta := structs.DefaultEnterpriseMetaInPartition(partition) idx, nodes, err := store.ServiceDump(ws, structs.ServiceKindMeshGateway, true, entMeta, structs.DefaultPeerKeyword) @@ -61,7 +61,7 @@ func (m *subscriptionManager) notifyMeshGatewaysForPartition(ctx context.Context func (m *subscriptionManager) syncViaBlockingQuery( ctx context.Context, queryType string, - queryFn func(ctx context.Context, store Store, ws memdb.WatchSet) (interface{}, error), + queryFn func(ctx context.Context, store StateStore, ws memdb.WatchSet) (interface{}, error), correlationID string, updateCh chan<- cache.UpdateEvent, ) { @@ -77,7 +77,7 @@ func (m *subscriptionManager) syncViaBlockingQuery( logger = m.logger.With("queryType", queryType) } - store := m.backend.Store() + store := m.getStore() for { ws := memdb.NewWatchSet() diff --git a/agent/rpc/peering/subscription_manager.go b/agent/grpc-external/services/peerstream/subscription_manager.go similarity index 96% rename from agent/rpc/peering/subscription_manager.go rename to agent/grpc-external/services/peerstream/subscription_manager.go index 9dfa135b5a..33726a216b 100644 --- a/agent/rpc/peering/subscription_manager.go +++ b/agent/grpc-external/services/peerstream/subscription_manager.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "context" @@ -29,7 +29,6 @@ type MaterializedViewStore interface { type SubscriptionBackend interface { Subscriber - Store() Store } // subscriptionManager handlers requests to subscribe to events from an events publisher. @@ -39,6 +38,7 @@ type subscriptionManager struct { trustDomain string viewStore MaterializedViewStore backend SubscriptionBackend + getStore func() StateStore } // TODO(peering): Maybe centralize so that there is a single manager per datacenter, rather than per peering. @@ -48,6 +48,7 @@ func newSubscriptionManager( config Config, trustDomain string, backend SubscriptionBackend, + getStore func() StateStore, ) *subscriptionManager { logger = logger.Named("subscriptions") store := submatview.NewStore(logger.Named("viewstore")) @@ -59,6 +60,7 @@ func newSubscriptionManager( trustDomain: trustDomain, viewStore: store, backend: backend, + getStore: getStore, } } @@ -167,13 +169,6 @@ func (m *subscriptionManager) handleEvent(ctx context.Context, state *subscripti // skip checks since we just generated one from scratch } - // Scrub raft indexes - for _, instance := range csn.Nodes { - instance.Node.RaftIndex = nil - instance.Service.RaftIndex = nil - // skip checks since we just generated one from scratch - } - id := servicePayloadIDPrefix + strings.TrimPrefix(u.CorrelationID, subExportedService) // Just ferry this one directly along to the destination. @@ -223,6 +218,9 @@ func (m *subscriptionManager) handleEvent(ctx context.Context, state *subscripti if instance.Service.Connect != nil || instance.Service.Proxy != nil { instance.Service.Connect = nil instance.Service.Proxy = nil + + // VirtualIPs assigned in this cluster won't make sense on the importing side + delete(instance.Service.TaggedAddresses, structs.TaggedAddressVirtualIP) } } @@ -284,6 +282,9 @@ func filterConnectReferences(orig *pbservice.IndexedCheckServiceNodes) { csn = proto.Clone(csn).(*pbservice.CheckServiceNode) csn.Service.Connect = nil csn.Service.Proxy = nil + + // VirtualIPs assigned in this cluster won't make sense on the importing side + delete(csn.Service.TaggedAddresses, structs.TaggedAddressVirtualIP) } newNodes = append(newNodes, csn) @@ -347,7 +348,7 @@ func (m *subscriptionManager) subscribeCARoots( // following a snapshot restore) reset idx to ensure we don't skip over the // new store's events. select { - case <-m.backend.Store().AbandonCh(): + case <-m.getStore().AbandonCh(): idx = 0 default: } @@ -556,6 +557,12 @@ func createDiscoChainHealth( trustDomain, ) + gwSpiffeID := connect.SpiffeIDMeshGateway{ + Host: trustDomain, + Partition: sn.PartitionOrDefault(), + Datacenter: datacenter, + } + // Create common peer meta. // // TODO(peering): should this be replicated by service and not by instance? @@ -563,19 +570,14 @@ func createDiscoChainHealth( SNI: []string{sni}, SpiffeID: []string{ mainSpiffeIDString, + // Always include the gateway id here to facilitate error-free + // L4/L7 upgrade/downgrade scenarios. + gwSpiffeID.URI().String(), }, Protocol: info.Protocol, } - if structs.IsProtocolHTTPLike(info.Protocol) { - gwSpiffeID := connect.SpiffeIDMeshGateway{ - Host: trustDomain, - Partition: sn.PartitionOrDefault(), - Datacenter: datacenter, - } - - peerMeta.SpiffeID = append(peerMeta.SpiffeID, gwSpiffeID.URI().String()) - } else { + if !structs.IsProtocolHTTPLike(info.Protocol) { for _, target := range info.TCPTargets { targetSpiffeID := connect.SpiffeIDService{ Host: trustDomain, diff --git a/agent/rpc/peering/subscription_manager_test.go b/agent/grpc-external/services/peerstream/subscription_manager_test.go similarity index 93% rename from agent/rpc/peering/subscription_manager_test.go rename to agent/grpc-external/services/peerstream/subscription_manager_test.go index 58e00f0780..cd12b2c221 100644 --- a/agent/rpc/peering/subscription_manager_test.go +++ b/agent/grpc-external/services/peerstream/subscription_manager_test.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "context" @@ -35,7 +35,9 @@ func TestSubscriptionManager_RegisterDeregister(t *testing.T) { mgr := newSubscriptionManager(ctx, testutil.Logger(t), Config{ Datacenter: "dc1", ConnectEnabled: true, - }, connect.TestTrustDomain, backend) + }, connect.TestTrustDomain, backend, func() StateStore { + return backend.store + }) subCh := mgr.subscribe(ctx, id, "my-peering", partition) var ( @@ -51,6 +53,19 @@ func TestSubscriptionManager_RegisterDeregister(t *testing.T) { checkEvent(t, got, gatewayCorrID, 0) }) + // Initially add in L4 failover so that later we can test removing it. We + // cannot do the other way around because it would fail validation to + // remove a target. + backend.ensureConfigEntry(t, &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "mysql", + Failover: map[string]structs.ServiceResolverFailover{ + "*": { + Service: "failover", + }, + }, + }) + testutil.RunStep(t, "initial export syncs empty instance lists", func(t *testing.T) { backend.ensureConfigEntry(t, &structs.ExportedServicesConfigEntry{ Name: "default", @@ -260,6 +275,8 @@ func TestSubscriptionManager_RegisterDeregister(t *testing.T) { }, SpiffeID: []string{ "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/mysql", + "spiffe://11111111-2222-3333-4444-555555555555.consul/gateway/mesh/dc/dc1", + "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/failover", }, Protocol: "tcp", }, @@ -285,12 +302,6 @@ func TestSubscriptionManager_RegisterDeregister(t *testing.T) { backend.ensureConfigEntry(t, &structs.ServiceResolverConfigEntry{ Kind: structs.ServiceResolver, Name: "mysql", - Failover: map[string]structs.ServiceResolverFailover{ - "*": { - Service: "failover", - Datacenters: []string{"dc2", "dc3"}, - }, - }, }) // ensure we get updated peer meta @@ -325,52 +336,7 @@ func TestSubscriptionManager_RegisterDeregister(t *testing.T) { }, SpiffeID: []string{ "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/mysql", - "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/failover", - "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc3/svc/failover", - }, - Protocol: "tcp", - }, - }, - }, - }, res.Nodes[0]) - }, - ) - - // reset so the next subtest is valid - backend.deleteConfigEntry(t, structs.ServiceResolver, "mysql") - - // ensure we get peer meta is restored - - expectEvents(t, subCh, - func(t *testing.T, got cache.UpdateEvent) { - require.Equal(t, mysqlProxyCorrID, got.CorrelationID) - res := got.Result.(*pbservice.IndexedCheckServiceNodes) - require.Equal(t, uint64(0), res.Index) - - require.Len(t, res.Nodes, 1) - prototest.AssertDeepEqual(t, &pbservice.CheckServiceNode{ - Node: pbNode("mgw", "10.1.1.1", partition), - Service: &pbservice.NodeService{ - Kind: "connect-proxy", - ID: "mysql-sidecar-proxy-instance-0", - Service: "mysql-sidecar-proxy", - Port: 8443, - Weights: &pbservice.Weights{ - Passing: 1, - Warning: 1, - }, - EnterpriseMeta: pbcommon.DefaultEnterpriseMeta, - Proxy: &pbservice.ConnectProxyConfig{ - DestinationServiceID: "mysql-instance-0", - DestinationServiceName: "mysql", - }, - Connect: &pbservice.ServiceConnect{ - PeerMeta: &pbservice.PeeringServiceMeta{ - SNI: []string{ - "mysql.default.default.my-peering.external.11111111-2222-3333-4444-555555555555.consul", - }, - SpiffeID: []string{ - "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/mysql", + "spiffe://11111111-2222-3333-4444-555555555555.consul/gateway/mesh/dc/dc1", }, Protocol: "tcp", }, @@ -479,7 +445,9 @@ func TestSubscriptionManager_InitialSnapshot(t *testing.T) { mgr := newSubscriptionManager(ctx, testutil.Logger(t), Config{ Datacenter: "dc1", ConnectEnabled: true, - }, connect.TestTrustDomain, backend) + }, connect.TestTrustDomain, backend, func() StateStore { + return backend.store + }) subCh := mgr.subscribe(ctx, id, "my-peering", partition) // Register two services that are not yet exported @@ -606,7 +574,9 @@ func TestSubscriptionManager_CARoots(t *testing.T) { mgr := newSubscriptionManager(ctx, testutil.Logger(t), Config{ Datacenter: "dc1", ConnectEnabled: true, - }, connect.TestTrustDomain, backend) + }, connect.TestTrustDomain, backend, func() StateStore { + return backend.store + }) subCh := mgr.subscribe(ctx, id, "my-peering", partition) testutil.RunStep(t, "initial events contain trust bundle", func(t *testing.T) { @@ -682,10 +652,6 @@ func newTestSubscriptionBackend(t *testing.T) *testSubscriptionBackend { return backend } -func (b *testSubscriptionBackend) Store() Store { - return b.store -} - func (b *testSubscriptionBackend) ensurePeering(t *testing.T, name string) (uint64, string) { b.lastIdx++ return b.lastIdx, setupTestPeering(t, b.store, name, b.lastIdx) diff --git a/agent/rpc/peering/subscription_state.go b/agent/grpc-external/services/peerstream/subscription_state.go similarity index 99% rename from agent/rpc/peering/subscription_state.go rename to agent/grpc-external/services/peerstream/subscription_state.go index dfb6942e2b..58e631f70a 100644 --- a/agent/rpc/peering/subscription_state.go +++ b/agent/grpc-external/services/peerstream/subscription_state.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "context" diff --git a/agent/rpc/peering/subscription_state_test.go b/agent/grpc-external/services/peerstream/subscription_state_test.go similarity index 99% rename from agent/rpc/peering/subscription_state_test.go rename to agent/grpc-external/services/peerstream/subscription_state_test.go index e94459ac66..b1846da5f5 100644 --- a/agent/rpc/peering/subscription_state_test.go +++ b/agent/grpc-external/services/peerstream/subscription_state_test.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "context" diff --git a/agent/rpc/peering/subscription_view.go b/agent/grpc-external/services/peerstream/subscription_view.go similarity index 99% rename from agent/rpc/peering/subscription_view.go rename to agent/grpc-external/services/peerstream/subscription_view.go index 7b6f9583ca..d8b17c76ab 100644 --- a/agent/rpc/peering/subscription_view.go +++ b/agent/grpc-external/services/peerstream/subscription_view.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "fmt" diff --git a/agent/rpc/peering/subscription_view_test.go b/agent/grpc-external/services/peerstream/subscription_view_test.go similarity index 99% rename from agent/rpc/peering/subscription_view_test.go rename to agent/grpc-external/services/peerstream/subscription_view_test.go index ae90c19ae7..c96b19bb21 100644 --- a/agent/rpc/peering/subscription_view_test.go +++ b/agent/grpc-external/services/peerstream/subscription_view_test.go @@ -1,4 +1,4 @@ -package peering +package peerstream import ( "context" diff --git a/agent/grpc-external/services/peerstream/testing.go b/agent/grpc-external/services/peerstream/testing.go new file mode 100644 index 0000000000..939c38dfa9 --- /dev/null +++ b/agent/grpc-external/services/peerstream/testing.go @@ -0,0 +1,128 @@ +package peerstream + +import ( + "context" + "io" + "sync" + "time" + + "google.golang.org/grpc/metadata" + + "github.com/hashicorp/consul/proto/pbpeerstream" +) + +type MockClient struct { + mu sync.Mutex + + ErrCh chan error + ReplicationStream *MockStream +} + +func (c *MockClient) Send(r *pbpeerstream.ReplicationMessage) error { + c.ReplicationStream.recvCh <- r + return nil +} + +func (c *MockClient) Recv() (*pbpeerstream.ReplicationMessage, error) { + select { + case err := <-c.ErrCh: + return nil, err + case r := <-c.ReplicationStream.sendCh: + return r, nil + case <-time.After(10 * time.Millisecond): + return nil, io.EOF + } +} + +func (c *MockClient) RecvWithTimeout(dur time.Duration) (*pbpeerstream.ReplicationMessage, error) { + select { + case err := <-c.ErrCh: + return nil, err + case r := <-c.ReplicationStream.sendCh: + return r, nil + case <-time.After(dur): + return nil, io.EOF + } +} + +func (c *MockClient) Close() { + close(c.ReplicationStream.recvCh) +} + +func NewMockClient(ctx context.Context) *MockClient { + return &MockClient{ + ReplicationStream: newTestReplicationStream(ctx), + } +} + +// MockStream mocks peering.PeeringService_StreamResourcesServer +type MockStream struct { + sendCh chan *pbpeerstream.ReplicationMessage + recvCh chan *pbpeerstream.ReplicationMessage + + ctx context.Context + mu sync.Mutex +} + +var _ pbpeerstream.PeerStreamService_StreamResourcesServer = (*MockStream)(nil) + +func newTestReplicationStream(ctx context.Context) *MockStream { + return &MockStream{ + sendCh: make(chan *pbpeerstream.ReplicationMessage, 1), + recvCh: make(chan *pbpeerstream.ReplicationMessage, 1), + ctx: ctx, + } +} + +// Send implements pbpeerstream.PeeringService_StreamResourcesServer +func (s *MockStream) Send(r *pbpeerstream.ReplicationMessage) error { + s.sendCh <- r + return nil +} + +// Recv implements pbpeerstream.PeeringService_StreamResourcesServer +func (s *MockStream) Recv() (*pbpeerstream.ReplicationMessage, error) { + r := <-s.recvCh + if r == nil { + return nil, io.EOF + } + return r, nil +} + +// Context implements grpc.ServerStream and grpc.ClientStream +func (s *MockStream) Context() context.Context { + return s.ctx +} + +// SendMsg implements grpc.ServerStream and grpc.ClientStream +func (s *MockStream) SendMsg(m interface{}) error { + return nil +} + +// RecvMsg implements grpc.ServerStream and grpc.ClientStream +func (s *MockStream) RecvMsg(m interface{}) error { + return nil +} + +// SetHeader implements grpc.ServerStream +func (s *MockStream) SetHeader(metadata.MD) error { + return nil +} + +// SendHeader implements grpc.ServerStream +func (s *MockStream) SendHeader(metadata.MD) error { + return nil +} + +// SetTrailer implements grpc.ServerStream +func (s *MockStream) SetTrailer(metadata.MD) {} + +type incrementalTime struct { + base time.Time + next uint64 +} + +func (t *incrementalTime) Now() time.Time { + t.next++ + return t.base.Add(time.Duration(t.next) * time.Second) +} diff --git a/agent/grpc/public/services/serverdiscovery/mock_ACLResolver.go b/agent/grpc-external/services/serverdiscovery/mock_ACLResolver.go similarity index 100% rename from agent/grpc/public/services/serverdiscovery/mock_ACLResolver.go rename to agent/grpc-external/services/serverdiscovery/mock_ACLResolver.go diff --git a/agent/grpc/public/services/serverdiscovery/server.go b/agent/grpc-external/services/serverdiscovery/server.go similarity index 100% rename from agent/grpc/public/services/serverdiscovery/server.go rename to agent/grpc-external/services/serverdiscovery/server.go diff --git a/agent/grpc/public/services/serverdiscovery/server_test.go b/agent/grpc-external/services/serverdiscovery/server_test.go similarity index 97% rename from agent/grpc/public/services/serverdiscovery/server_test.go rename to agent/grpc-external/services/serverdiscovery/server_test.go index 2ad8e51201..c946adaa8c 100644 --- a/agent/grpc/public/services/serverdiscovery/server_test.go +++ b/agent/grpc-external/services/serverdiscovery/server_test.go @@ -12,7 +12,7 @@ import ( "github.com/hashicorp/consul/agent/consul/autopilotevents" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/proto-public/pbserverdiscovery" ) diff --git a/agent/grpc/public/services/serverdiscovery/watch_servers.go b/agent/grpc-external/services/serverdiscovery/watch_servers.go similarity index 95% rename from agent/grpc/public/services/serverdiscovery/watch_servers.go rename to agent/grpc-external/services/serverdiscovery/watch_servers.go index 6ceda83ffe..1a119148cc 100644 --- a/agent/grpc/public/services/serverdiscovery/watch_servers.go +++ b/agent/grpc-external/services/serverdiscovery/watch_servers.go @@ -4,15 +4,16 @@ import ( "context" "errors" - "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/consul/autopilotevents" - "github.com/hashicorp/consul/agent/consul/stream" - "github.com/hashicorp/consul/agent/grpc/public" - "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/proto-public/pbserverdiscovery" "github.com/hashicorp/go-hclog" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/consul/autopilotevents" + "github.com/hashicorp/consul/agent/consul/stream" + external "github.com/hashicorp/consul/agent/grpc-external" + "github.com/hashicorp/consul/agent/structs" + "github.com/hashicorp/consul/proto-public/pbserverdiscovery" ) // WatchServers provides a stream on which you can receive the list of servers @@ -20,12 +21,12 @@ import ( // current set of ready servers are sent immediately at the start of the // stream and new updates will be sent whenver the set of ready servers changes. func (s *Server) WatchServers(req *pbserverdiscovery.WatchServersRequest, serverStream pbserverdiscovery.ServerDiscoveryService_WatchServersServer) error { - logger := s.Logger.Named("watch-servers").With("request_id", public.TraceID()) + logger := s.Logger.Named("watch-servers").With("request_id", external.TraceID()) logger.Debug("starting stream") defer logger.Trace("stream closed") - token := public.TokenFromContext(serverStream.Context()) + token := external.TokenFromContext(serverStream.Context()) // Serve the ready servers from an EventPublisher subscription. If the subscription is // closed due to an ACL change, we'll attempt to re-authorize and resume it to diff --git a/agent/grpc/public/services/serverdiscovery/watch_servers_test.go b/agent/grpc-external/services/serverdiscovery/watch_servers_test.go similarity index 96% rename from agent/grpc/public/services/serverdiscovery/watch_servers_test.go rename to agent/grpc-external/services/serverdiscovery/watch_servers_test.go index a44520e558..1a73b06689 100644 --- a/agent/grpc/public/services/serverdiscovery/watch_servers_test.go +++ b/agent/grpc-external/services/serverdiscovery/watch_servers_test.go @@ -16,8 +16,8 @@ import ( resolver "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/consul/autopilotevents" "github.com/hashicorp/consul/agent/consul/stream" - "github.com/hashicorp/consul/agent/grpc/public" - "github.com/hashicorp/consul/agent/grpc/public/testutils" + external "github.com/hashicorp/consul/agent/grpc-external" + "github.com/hashicorp/consul/agent/grpc-external/testutils" "github.com/hashicorp/consul/proto-public/pbserverdiscovery" "github.com/hashicorp/consul/proto/prototest" "github.com/hashicorp/consul/sdk/testutil" @@ -125,7 +125,7 @@ func TestWatchServers_StreamLifeCycle(t *testing.T) { Return(testutils.TestAuthorizerServiceWriteAny(t), nil).Twice() // add the token to the requests context - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) // setup the server server := NewServer(Config{ @@ -198,7 +198,7 @@ func TestWatchServers_ACLToken_PermissionDenied(t *testing.T) { Return(testutils.TestAuthorizerDenyAll(t), nil).Once() // add the token to the requests context - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) // setup the server server := NewServer(Config{ @@ -229,7 +229,7 @@ func TestWatchServers_ACLToken_Unauthenticated(t *testing.T) { Return(resolver.Result{}, acl.ErrNotFound).Once() // add the token to the requests context - ctx := public.ContextWithToken(context.Background(), testACLToken) + ctx := external.ContextWithToken(context.Background(), testACLToken) // setup the server server := NewServer(Config{ diff --git a/agent/grpc/public/testutils/acl.go b/agent/grpc-external/testutils/acl.go similarity index 100% rename from agent/grpc/public/testutils/acl.go rename to agent/grpc-external/testutils/acl.go diff --git a/agent/grpc/public/testutils/fsm.go b/agent/grpc-external/testutils/fsm.go similarity index 100% rename from agent/grpc/public/testutils/fsm.go rename to agent/grpc-external/testutils/fsm.go diff --git a/agent/grpc/public/testutils/server.go b/agent/grpc-external/testutils/server.go similarity index 100% rename from agent/grpc/public/testutils/server.go rename to agent/grpc-external/testutils/server.go diff --git a/agent/grpc/public/token.go b/agent/grpc-external/token.go similarity index 97% rename from agent/grpc/public/token.go rename to agent/grpc-external/token.go index 237317ee4c..68006b254e 100644 --- a/agent/grpc/public/token.go +++ b/agent/grpc-external/token.go @@ -1,4 +1,4 @@ -package public +package external import ( "context" diff --git a/agent/grpc/public/utils.go b/agent/grpc-external/utils.go similarity index 94% rename from agent/grpc/public/utils.go rename to agent/grpc-external/utils.go index 70d7d1abb5..c2c77ace64 100644 --- a/agent/grpc/public/utils.go +++ b/agent/grpc-external/utils.go @@ -1,4 +1,4 @@ -package public +package external import "github.com/hashicorp/go-uuid" diff --git a/agent/grpc/private/client.go b/agent/grpc-internal/client.go similarity index 99% rename from agent/grpc/private/client.go rename to agent/grpc-internal/client.go index 8d10edd175..451a5236ea 100644 --- a/agent/grpc/private/client.go +++ b/agent/grpc-internal/client.go @@ -1,4 +1,4 @@ -package private +package internal import ( "context" diff --git a/agent/grpc/private/client_test.go b/agent/grpc-internal/client_test.go similarity index 94% rename from agent/grpc/private/client_test.go rename to agent/grpc-internal/client_test.go index d414207abe..e36cd6aad6 100644 --- a/agent/grpc/private/client_test.go +++ b/agent/grpc-internal/client_test.go @@ -1,4 +1,4 @@ -package private +package internal import ( "context" @@ -14,8 +14,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/hashicorp/consul/agent/grpc/private/internal/testservice" - "github.com/hashicorp/consul/agent/grpc/private/resolver" + "github.com/hashicorp/consul/agent/grpc-internal/internal/testservice" + "github.com/hashicorp/consul/agent/grpc-internal/resolver" "github.com/hashicorp/consul/agent/metadata" "github.com/hashicorp/consul/ipaddr" "github.com/hashicorp/consul/sdk/freeport" @@ -145,9 +145,9 @@ func TestNewDialer_IntegrationWithTLSEnabledHandler(t *testing.T) { tlsConf, err := tlsutil.NewConfigurator(tlsutil.Config{ InternalRPC: tlsutil.ProtocolConfig{ VerifyIncoming: true, - CAFile: "../../../test/hostname/CertAuth.crt", - CertFile: "../../../test/hostname/Alice.crt", - KeyFile: "../../../test/hostname/Alice.key", + CAFile: "../../test/hostname/CertAuth.crt", + CertFile: "../../test/hostname/Alice.crt", + KeyFile: "../../test/hostname/Alice.key", VerifyOutgoing: true, }, }, hclog.New(nil)) @@ -192,9 +192,9 @@ func TestNewDialer_IntegrationWithTLSEnabledHandler_viaMeshGateway(t *testing.T) tlsConf, err := tlsutil.NewConfigurator(tlsutil.Config{ InternalRPC: tlsutil.ProtocolConfig{ VerifyIncoming: true, - CAFile: "../../../test/hostname/CertAuth.crt", - CertFile: "../../../test/hostname/Bob.crt", - KeyFile: "../../../test/hostname/Bob.key", + CAFile: "../../test/hostname/CertAuth.crt", + CertFile: "../../test/hostname/Bob.crt", + KeyFile: "../../test/hostname/Bob.key", VerifyOutgoing: true, VerifyServerHostname: true, }, @@ -222,9 +222,9 @@ func TestNewDialer_IntegrationWithTLSEnabledHandler_viaMeshGateway(t *testing.T) clientTLSConf, err := tlsutil.NewConfigurator(tlsutil.Config{ InternalRPC: tlsutil.ProtocolConfig{ VerifyIncoming: true, - CAFile: "../../../test/hostname/CertAuth.crt", - CertFile: "../../../test/hostname/Betty.crt", - KeyFile: "../../../test/hostname/Betty.key", + CAFile: "../../test/hostname/CertAuth.crt", + CertFile: "../../test/hostname/Betty.crt", + KeyFile: "../../test/hostname/Betty.key", VerifyOutgoing: true, VerifyServerHostname: true, }, diff --git a/agent/grpc/private/handler.go b/agent/grpc-internal/handler.go similarity index 97% rename from agent/grpc/private/handler.go rename to agent/grpc-internal/handler.go index 3cc103af28..b5e7d2573a 100644 --- a/agent/grpc/private/handler.go +++ b/agent/grpc-internal/handler.go @@ -1,11 +1,11 @@ -package private +package internal import ( "fmt" "net" "time" - agentmiddleware "github.com/hashicorp/consul/agent/grpc/middleware" + agentmiddleware "github.com/hashicorp/consul/agent/grpc-middleware" middleware "github.com/grpc-ecosystem/go-grpc-middleware" recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" diff --git a/agent/grpc/private/handler_test.go b/agent/grpc-internal/handler_test.go similarity index 89% rename from agent/grpc/private/handler_test.go rename to agent/grpc-internal/handler_test.go index 6edf82195f..f538773019 100644 --- a/agent/grpc/private/handler_test.go +++ b/agent/grpc-internal/handler_test.go @@ -1,4 +1,4 @@ -package private +package internal import ( "bytes" @@ -13,8 +13,8 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/hashicorp/consul/agent/grpc/private/internal/testservice" - "github.com/hashicorp/consul/agent/grpc/private/resolver" + "github.com/hashicorp/consul/agent/grpc-internal/internal/testservice" + "github.com/hashicorp/consul/agent/grpc-internal/resolver" ) func TestHandler_PanicRecoveryInterceptor(t *testing.T) { @@ -57,5 +57,5 @@ func TestHandler_PanicRecoveryInterceptor(t *testing.T) { // Checking the entire stack trace is not possible, let's // make sure that it contains a couple of expected strings. require.Contains(t, strLog, `[ERROR] panic serving grpc request: panic="panic from Something`) - require.Contains(t, strLog, `github.com/hashicorp/consul/agent/grpc/private.(*simplePanic).Something`) + require.Contains(t, strLog, `github.com/hashicorp/consul/agent/grpc-internal.(*simplePanic).Something`) } diff --git a/agent/grpc/private/internal/testservice/simple.pb.binary.go b/agent/grpc-internal/internal/testservice/simple.pb.binary.go similarity index 91% rename from agent/grpc/private/internal/testservice/simple.pb.binary.go rename to agent/grpc-internal/internal/testservice/simple.pb.binary.go index 2d65084bd8..fd2d7e13f1 100644 --- a/agent/grpc/private/internal/testservice/simple.pb.binary.go +++ b/agent/grpc-internal/internal/testservice/simple.pb.binary.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-binary. DO NOT EDIT. -// source: agent/grpc/private/internal/testservice/simple.proto +// source: agent/grpc-internal/internal/testservice/simple.proto package testservice diff --git a/agent/grpc/private/internal/testservice/simple.pb.go b/agent/grpc-internal/internal/testservice/simple.pb.go similarity index 98% rename from agent/grpc/private/internal/testservice/simple.pb.go rename to agent/grpc-internal/internal/testservice/simple.pb.go index 4f12adeb9d..dfca35fa00 100644 --- a/agent/grpc/private/internal/testservice/simple.pb.go +++ b/agent/grpc-internal/internal/testservice/simple.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go v1.23.0 // protoc v3.15.8 -// source: agent/grpc/private/internal/testservice/simple.proto +// source: agent/grpc-internal/internal/testservice/simple.proto package testservice @@ -376,5 +376,5 @@ var _Simple_serviceDesc = grpc.ServiceDesc{ ServerStreams: true, }, }, - Metadata: "agent/grpc/private/internal/testservice/simple.proto", + Metadata: "agent/grpc-internal/internal/testservice/simple.proto", } diff --git a/agent/grpc/private/internal/testservice/simple.proto b/agent/grpc-internal/internal/testservice/simple.proto similarity index 76% rename from agent/grpc/private/internal/testservice/simple.proto rename to agent/grpc-internal/internal/testservice/simple.proto index 31a53308fb..bcace657ac 100644 --- a/agent/grpc/private/internal/testservice/simple.proto +++ b/agent/grpc-internal/internal/testservice/simple.proto @@ -2,7 +2,7 @@ syntax = "proto3"; package testservice; -option go_package = "github.com/hashicorp/consul/agent/grpc/private/internal/testservice"; +option go_package = "github.com/hashicorp/consul/agent/grpc-internal/internal/testservice"; // Simple service is used to test gRPC plumbing. service Simple { diff --git a/agent/grpc/private/resolver/registry.go b/agent/grpc-internal/resolver/registry.go similarity index 100% rename from agent/grpc/private/resolver/registry.go rename to agent/grpc-internal/resolver/registry.go diff --git a/agent/grpc/private/resolver/resolver.go b/agent/grpc-internal/resolver/resolver.go similarity index 100% rename from agent/grpc/private/resolver/resolver.go rename to agent/grpc-internal/resolver/resolver.go diff --git a/agent/grpc/private/server_test.go b/agent/grpc-internal/server_test.go similarity index 98% rename from agent/grpc/private/server_test.go rename to agent/grpc-internal/server_test.go index c9873c2226..45e1ad59fd 100644 --- a/agent/grpc/private/server_test.go +++ b/agent/grpc-internal/server_test.go @@ -1,4 +1,4 @@ -package private +package internal import ( "context" @@ -15,7 +15,7 @@ import ( "golang.org/x/sync/errgroup" "google.golang.org/grpc" - "github.com/hashicorp/consul/agent/grpc/private/internal/testservice" + "github.com/hashicorp/consul/agent/grpc-internal/internal/testservice" "github.com/hashicorp/consul/agent/metadata" "github.com/hashicorp/consul/agent/pool" "github.com/hashicorp/consul/tlsutil" diff --git a/agent/grpc/private/services/subscribe/logger.go b/agent/grpc-internal/services/subscribe/logger.go similarity index 100% rename from agent/grpc/private/services/subscribe/logger.go rename to agent/grpc-internal/services/subscribe/logger.go diff --git a/agent/grpc/private/services/subscribe/subscribe.go b/agent/grpc-internal/services/subscribe/subscribe.go similarity index 100% rename from agent/grpc/private/services/subscribe/subscribe.go rename to agent/grpc-internal/services/subscribe/subscribe.go diff --git a/agent/grpc/private/services/subscribe/subscribe_test.go b/agent/grpc-internal/services/subscribe/subscribe_test.go similarity index 99% rename from agent/grpc/private/services/subscribe/subscribe_test.go rename to agent/grpc-internal/services/subscribe/subscribe_test.go index e5018ca386..26a8e148cb 100644 --- a/agent/grpc/private/services/subscribe/subscribe_test.go +++ b/agent/grpc-internal/services/subscribe/subscribe_test.go @@ -21,7 +21,7 @@ import ( "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" - grpc "github.com/hashicorp/consul/agent/grpc/private" + grpc "github.com/hashicorp/consul/agent/grpc-internal" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/proto/pbcommon" diff --git a/agent/grpc/private/stats.go b/agent/grpc-internal/stats.go similarity index 99% rename from agent/grpc/private/stats.go rename to agent/grpc-internal/stats.go index 76293e8511..ab5226cee2 100644 --- a/agent/grpc/private/stats.go +++ b/agent/grpc-internal/stats.go @@ -1,4 +1,4 @@ -package private +package internal import ( "context" diff --git a/agent/grpc/private/stats_test.go b/agent/grpc-internal/stats_test.go similarity index 97% rename from agent/grpc/private/stats_test.go rename to agent/grpc-internal/stats_test.go index 0d7268e4e8..a32ea55251 100644 --- a/agent/grpc/private/stats_test.go +++ b/agent/grpc-internal/stats_test.go @@ -1,4 +1,4 @@ -package private +package internal import ( "context" @@ -14,9 +14,10 @@ import ( "golang.org/x/sync/errgroup" "google.golang.org/grpc" - "github.com/hashicorp/consul/agent/grpc/private/internal/testservice" - "github.com/hashicorp/consul/proto/prototest" "github.com/hashicorp/go-hclog" + + "github.com/hashicorp/consul/agent/grpc-internal/internal/testservice" + "github.com/hashicorp/consul/proto/prototest" ) func noopRegister(*grpc.Server) {} diff --git a/agent/grpc/middleware/recovery.go b/agent/grpc-middleware/recovery.go similarity index 100% rename from agent/grpc/middleware/recovery.go rename to agent/grpc-middleware/recovery.go diff --git a/agent/metadata/server.go b/agent/metadata/server.go index 3715032c6a..83997f7cd1 100644 --- a/agent/metadata/server.go +++ b/agent/metadata/server.go @@ -23,25 +23,26 @@ func (k *Key) Equal(x *Key) bool { // Server is used to return details of a consul server type Server struct { - Name string // . - ShortName string // - ID string - Datacenter string - Segment string - Port int - SegmentAddrs map[string]string - SegmentPorts map[string]int - WanJoinPort int - LanJoinPort int - Bootstrap bool - Expect int - Build version.Version - Version int - RaftVersion int - Addr net.Addr - Status serf.MemberStatus - ReadReplica bool - FeatureFlags map[string]int + Name string // . + ShortName string // + ID string + Datacenter string + Segment string + Port int + SegmentAddrs map[string]string + SegmentPorts map[string]int + WanJoinPort int + LanJoinPort int + ExternalGRPCPort int + Bootstrap bool + Expect int + Build version.Version + Version int + RaftVersion int + Addr net.Addr + Status serf.MemberStatus + ReadReplica bool + FeatureFlags map[string]int // If true, use TLS when connecting to this server UseTLS bool @@ -136,6 +137,18 @@ func IsConsulServer(m serf.Member) (bool, *Server) { } } + externalGRPCPort := 0 + externalGRPCPortStr, ok := m.Tags["grpc_port"] + if ok { + externalGRPCPort, err = strconv.Atoi(externalGRPCPortStr) + if err != nil { + return false, nil + } + if externalGRPCPort < 1 { + return false, nil + } + } + vsnStr := m.Tags["vsn"] vsn, err := strconv.Atoi(vsnStr) if err != nil { @@ -160,24 +173,25 @@ func IsConsulServer(m serf.Member) (bool, *Server) { addr := &net.TCPAddr{IP: m.Addr, Port: port} parts := &Server{ - Name: m.Name, - ShortName: strings.TrimSuffix(m.Name, "."+datacenter), - ID: m.Tags["id"], - Datacenter: datacenter, - Segment: segment, - Port: port, - SegmentAddrs: segmentAddrs, - SegmentPorts: segmentPorts, - WanJoinPort: wanJoinPort, - LanJoinPort: int(m.Port), - Bootstrap: bootstrap, - Expect: expect, - Addr: addr, - Build: *buildVersion, - Version: vsn, - RaftVersion: raftVsn, - Status: m.Status, - UseTLS: useTLS, + Name: m.Name, + ShortName: strings.TrimSuffix(m.Name, "."+datacenter), + ID: m.Tags["id"], + Datacenter: datacenter, + Segment: segment, + Port: port, + SegmentAddrs: segmentAddrs, + SegmentPorts: segmentPorts, + WanJoinPort: wanJoinPort, + LanJoinPort: int(m.Port), + ExternalGRPCPort: externalGRPCPort, + Bootstrap: bootstrap, + Expect: expect, + Addr: addr, + Build: *buildVersion, + Version: vsn, + RaftVersion: raftVsn, + Status: m.Status, + UseTLS: useTLS, // DEPRECATED - remove nonVoter check once support for that tag is removed ReadReplica: nonVoter || readReplica, FeatureFlags: featureFlags, diff --git a/agent/metadata/server_test.go b/agent/metadata/server_test.go index e83a4b0874..2f56bd7fd4 100644 --- a/agent/metadata/server_test.go +++ b/agent/metadata/server_test.go @@ -4,6 +4,7 @@ import ( "net" "testing" + "github.com/hashicorp/go-version" "github.com/hashicorp/serf/serf" "github.com/stretchr/testify/require" @@ -53,173 +54,136 @@ func TestServer_Key_params(t *testing.T) { } func TestIsConsulServer(t *testing.T) { - m := serf.Member{ - Name: "foo", - Addr: net.IP([]byte{127, 0, 0, 1}), - Tags: map[string]string{ - "role": "consul", - "id": "asdf", - "dc": "east-aws", - "port": "10000", - "build": "0.8.0", - "wan_join_port": "1234", - "vsn": "1", - "expect": "3", - "raft_vsn": "3", - "use_tls": "1", - "read_replica": "1", - }, - Status: serf.StatusLeft, - } - ok, parts := metadata.IsConsulServer(m) - if !ok || parts.Datacenter != "east-aws" || parts.Port != 10000 { - t.Fatalf("bad: %v %v", ok, parts) - } - if parts.Name != "foo" { - t.Fatalf("bad: %v", parts) - } - if parts.ID != "asdf" { - t.Fatalf("bad: %v", parts.ID) - } - if parts.Bootstrap { - t.Fatalf("unexpected bootstrap") - } - if parts.Expect != 3 { - t.Fatalf("bad: %v", parts.Expect) - } - if parts.Port != 10000 { - t.Fatalf("bad: %v", parts.Port) - } - if parts.WanJoinPort != 1234 { - t.Fatalf("bad: %v", parts.WanJoinPort) - } - if parts.RaftVersion != 3 { - t.Fatalf("bad: %v", parts.RaftVersion) - } - if parts.Status != serf.StatusLeft { - t.Fatalf("bad: %v", parts.Status) - } - if !parts.UseTLS { - t.Fatalf("bad: %v", parts.UseTLS) - } - if !parts.ReadReplica { - t.Fatalf("unexpected voter") - } - m.Tags["bootstrap"] = "1" - m.Tags["disabled"] = "1" - ok, parts = metadata.IsConsulServer(m) - if !ok { - t.Fatalf("expected a valid consul server") - } - if !parts.Bootstrap { - t.Fatalf("expected bootstrap") - } - if parts.Addr.String() != "127.0.0.1:10000" { - t.Fatalf("bad addr: %v", parts.Addr) - } - if parts.Version != 1 { - t.Fatalf("bad: %v", parts) - } - m.Tags["expect"] = "3" - delete(m.Tags, "bootstrap") - delete(m.Tags, "disabled") - ok, parts = metadata.IsConsulServer(m) - if !ok || parts.Expect != 3 { - t.Fatalf("bad: %v", parts.Expect) - } - if parts.Bootstrap { - t.Fatalf("unexpected bootstrap") + mustVersion := func(s string) *version.Version { + v, err := version.NewVersion(s) + require.NoError(t, err) + return v } - delete(m.Tags, "read_replica") - ok, parts = metadata.IsConsulServer(m) - if !ok || parts.ReadReplica { - t.Fatalf("unexpected read replica") - } + newCase := func(variant string) (in serf.Member, expect *metadata.Server) { + m := serf.Member{ + Name: "foo", + Addr: net.IP([]byte{127, 0, 0, 1}), + Port: 5454, + Tags: map[string]string{ + "role": "consul", + "id": "asdf", + "dc": "east-aws", + "port": "10000", + "build": "0.8.0", + "wan_join_port": "1234", + "grpc_port": "9876", + "vsn": "1", + "expect": "3", + "raft_vsn": "3", + "use_tls": "1", + }, + Status: serf.StatusLeft, + } - m.Tags["nonvoter"] = "1" - ok, parts = metadata.IsConsulServer(m) - if !ok || !parts.ReadReplica { - t.Fatalf("expected read replica") - } + expected := &metadata.Server{ + Name: "foo", + ShortName: "foo", + ID: "asdf", + Datacenter: "east-aws", + Segment: "", + Port: 10000, + SegmentAddrs: map[string]string{}, + SegmentPorts: map[string]int{}, + WanJoinPort: 1234, + LanJoinPort: 5454, + ExternalGRPCPort: 9876, + Bootstrap: false, + Expect: 3, + Addr: &net.TCPAddr{ + IP: net.IP([]byte{127, 0, 0, 1}), + Port: 10000, + }, + Build: *mustVersion("0.8.0"), + Version: 1, + RaftVersion: 3, + Status: serf.StatusLeft, + UseTLS: true, + ReadReplica: false, + FeatureFlags: map[string]int{}, + } - delete(m.Tags, "role") - ok, _ = metadata.IsConsulServer(m) - require.False(t, ok, "expected to not be a consul server") -} - -func TestIsConsulServer_Optional(t *testing.T) { - m := serf.Member{ - Name: "foo", - Addr: net.IP([]byte{127, 0, 0, 1}), - Tags: map[string]string{ - "role": "consul", - "id": "asdf", - "dc": "east-aws", - "port": "10000", - "vsn": "1", - "build": "0.8.0", - // wan_join_port, raft_vsn, and expect are optional and + switch variant { + case "normal": + case "read-replica": + m.Tags["read_replica"] = "1" + expected.ReadReplica = true + case "non-voter": + m.Tags["nonvoter"] = "1" + expected.ReadReplica = true + case "expect-3": + m.Tags["expect"] = "3" + expected.Expect = 3 + case "bootstrapped": + m.Tags["bootstrap"] = "1" + m.Tags["disabled"] = "1" + expected.Bootstrap = true + case "optionals": + // grpc_port, wan_join_port, raft_vsn, and expect are optional and // should default to zero. - }, - } - ok, parts := metadata.IsConsulServer(m) - if !ok || parts.Datacenter != "east-aws" || parts.Port != 10000 { - t.Fatalf("bad: %v %v", ok, parts) - } - if parts.Name != "foo" { - t.Fatalf("bad: %v", parts) - } - if parts.ID != "asdf" { - t.Fatalf("bad: %v", parts.ID) - } - if parts.Bootstrap { - t.Fatalf("unexpected bootstrap") - } - if parts.Expect != 0 { - t.Fatalf("bad: %v", parts.Expect) - } - if parts.Port != 10000 { - t.Fatalf("bad: %v", parts.Port) - } - if parts.WanJoinPort != 0 { - t.Fatalf("bad: %v", parts.WanJoinPort) - } - if parts.RaftVersion != 0 { - t.Fatalf("bad: %v", parts.RaftVersion) + delete(m.Tags, "grpc_port") + delete(m.Tags, "wan_join_port") + delete(m.Tags, "raft_vsn") + delete(m.Tags, "expect") + expected.RaftVersion = 0 + expected.Expect = 0 + expected.WanJoinPort = 0 + expected.ExternalGRPCPort = 0 + case "feature-namespaces": + m.Tags["ft_ns"] = "1" + expected.FeatureFlags = map[string]int{"ns": 1} + // + case "bad-grpc-port": + m.Tags["grpc_port"] = "three" + case "negative-grpc-port": + m.Tags["grpc_port"] = "-1" + case "zero-grpc-port": + m.Tags["grpc_port"] = "0" + case "no-role": + delete(m.Tags, "role") + default: + t.Fatalf("unhandled variant: %s", variant) + } + + return m, expected } - m.Tags["bootstrap"] = "1" - m.Tags["disabled"] = "1" - m.Tags["ft_ns"] = "1" - ok, parts = metadata.IsConsulServer(m) - if !ok { - t.Fatalf("expected a valid consul server") - } - if !parts.Bootstrap { - t.Fatalf("expected bootstrap") - } - if parts.Addr.String() != "127.0.0.1:10000" { - t.Fatalf("bad addr: %v", parts.Addr) - } - if parts.Version != 1 { - t.Fatalf("bad: %v", parts) - } - expectedFlags := map[string]int{"ns": 1} - require.Equal(t, expectedFlags, parts.FeatureFlags) + run := func(t *testing.T, variant string, expectOK bool) { + m, expected := newCase(variant) + ok, parts := metadata.IsConsulServer(m) - m.Tags["expect"] = "3" - delete(m.Tags, "bootstrap") - delete(m.Tags, "disabled") - ok, parts = metadata.IsConsulServer(m) - if !ok || parts.Expect != 3 { - t.Fatalf("bad: %v", parts.Expect) - } - if parts.Bootstrap { - t.Fatalf("unexpected bootstrap") + if expectOK { + require.True(t, ok, "expected a valid consul server") + require.Equal(t, expected, parts) + } else { + ok, _ := metadata.IsConsulServer(m) + require.False(t, ok, "expected to not be a consul server") + } } - delete(m.Tags, "role") - ok, _ = metadata.IsConsulServer(m) - require.False(t, ok, "expected to not be a consul server") + cases := map[string]bool{ + "normal": true, + "read-replica": true, + "non-voter": true, + "expect-3": true, + "bootstrapped": true, + "optionals": true, + "feature-namespaces": true, + // + "no-role": false, + "bad-grpc-port": false, + "negative-grpc-port": false, + "zero-grpc-port": false, + } + + for variant, expectOK := range cases { + t.Run(variant, func(t *testing.T) { + run(t, variant, expectOK) + }) + } } diff --git a/agent/peering_endpoint_test.go b/agent/peering_endpoint_test.go index b9aee1ab45..545e4f5ecb 100644 --- a/agent/peering_endpoint_test.go +++ b/agent/peering_endpoint_test.go @@ -107,7 +107,7 @@ func TestHTTP_Peering_GenerateToken(t *testing.T) { require.NoError(t, json.Unmarshal(tokenJSON, &token)) require.Nil(t, token.CA) - require.Equal(t, []string{fmt.Sprintf("127.0.0.1:%d", a.config.ServerPort)}, token.ServerAddresses) + require.Equal(t, []string{fmt.Sprintf("127.0.0.1:%d", a.config.GRPCPort)}, token.ServerAddresses) require.Equal(t, "server.dc1.consul", token.ServerName) // The PeerID in the token is randomly generated so we don't assert on its value. diff --git a/agent/pool/pool.go b/agent/pool/pool.go index acfe73065e..fa223790d2 100644 --- a/agent/pool/pool.go +++ b/agent/pool/pool.go @@ -451,7 +451,7 @@ func DialRPCViaMeshGateway( } if nextProto != ALPN_RPCGRPC { - // agent/grpc/private/client.go:dial() handles this in another way for gRPC + // agent/grpc-internal/client.go:dial() handles this in another way for gRPC if tcp, ok := rawConn.(*net.TCPConn); ok { _ = tcp.SetKeepAlive(true) _ = tcp.SetNoDelay(true) diff --git a/agent/proxycfg/connect_proxy.go b/agent/proxycfg/connect_proxy.go index ab86560bd5..3221150dba 100644 --- a/agent/proxycfg/connect_proxy.go +++ b/agent/proxycfg/connect_proxy.go @@ -6,6 +6,7 @@ import ( "strings" cachetype "github.com/hashicorp/consul/agent/cache-types" + "github.com/hashicorp/consul/agent/proxycfg/internal/watch" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/pbpeering" ) @@ -22,8 +23,7 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e snap.ConnectProxy.WatchedDiscoveryChains = make(map[UpstreamID]context.CancelFunc) snap.ConnectProxy.WatchedUpstreams = make(map[UpstreamID]map[string]context.CancelFunc) snap.ConnectProxy.WatchedUpstreamEndpoints = make(map[UpstreamID]map[string]structs.CheckServiceNodes) - snap.ConnectProxy.WatchedUpstreamPeerTrustBundles = make(map[string]context.CancelFunc) - snap.ConnectProxy.UpstreamPeerTrustBundles = make(map[string]*pbpeering.PeeringTrustBundle) + snap.ConnectProxy.UpstreamPeerTrustBundles = watch.NewMap[string, *pbpeering.PeeringTrustBundle]() snap.ConnectProxy.WatchedGateways = make(map[UpstreamID]map[string]context.CancelFunc) snap.ConnectProxy.WatchedGatewayEndpoints = make(map[UpstreamID]map[string]structs.CheckServiceNodes) snap.ConnectProxy.WatchedServiceChecks = make(map[structs.ServiceID][]structs.CheckType) @@ -31,7 +31,7 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e snap.ConnectProxy.UpstreamConfig = make(map[UpstreamID]*structs.Upstream) snap.ConnectProxy.PassthroughUpstreams = make(map[UpstreamID]map[string]map[string]struct{}) snap.ConnectProxy.PassthroughIndices = make(map[string]indexedTarget) - snap.ConnectProxy.PeerUpstreamEndpoints = make(map[UpstreamID]structs.CheckServiceNodes) + snap.ConnectProxy.PeerUpstreamEndpoints = watch.NewMap[UpstreamID, structs.CheckServiceNodes]() snap.ConnectProxy.PeerUpstreamEndpointsUseHostnames = make(map[UpstreamID]struct{}) // Watch for root changes @@ -108,6 +108,14 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e if err != nil { return snap, err } + err = s.dataSources.PeeredUpstreams.Notify(ctx, &structs.PartitionSpecificRequest{ + QueryOptions: structs.QueryOptions{Token: s.token}, + Datacenter: s.source.Datacenter, + EnterpriseMeta: s.proxyID.EnterpriseMeta, + }, peeredUpstreamsID, s.ch) + if err != nil { + return snap, err + } } // Watch for updates to service endpoints for all upstreams @@ -134,7 +142,8 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e dc = u.Datacenter } if s.proxyCfg.Mode == structs.ProxyModeTransparent && (dc == "" || dc == s.source.Datacenter) { - // In transparent proxy mode, watches for upstreams in the local DC are handled by the IntentionUpstreams watch. + // In transparent proxy mode, watches for upstreams in the local DC + // are handled by the IntentionUpstreams and PeeredUpstreams watch. continue } @@ -183,8 +192,7 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e s.logger.Trace("initializing watch of peered upstream", "upstream", uid) - // TODO(peering): We'll need to track a CancelFunc for this - // once the tproxy support lands. + snap.ConnectProxy.PeerUpstreamEndpoints.InitWatch(uid, nil) err := s.dataSources.Health.Notify(ctx, &structs.ServiceSpecificRequest{ PeerName: uid.Peer, Datacenter: dc, @@ -204,7 +212,7 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e } // Check whether a watch for this peer exists to avoid duplicates. - if _, ok := snap.ConnectProxy.WatchedUpstreamPeerTrustBundles[uid.Peer]; !ok { + if _, ok := snap.ConnectProxy.UpstreamPeerTrustBundles.Get(uid.Peer); !ok { peerCtx, cancel := context.WithCancel(ctx) if err := s.dataSources.TrustBundle.Notify(peerCtx, &pbpeering.TrustBundleReadRequest{ Name: uid.Peer, @@ -214,7 +222,7 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e return snap, fmt.Errorf("error while watching trust bundle for peer %q: %w", uid.Peer, err) } - snap.ConnectProxy.WatchedUpstreamPeerTrustBundles[uid.Peer] = cancel + snap.ConnectProxy.UpstreamPeerTrustBundles.InitWatch(uid.Peer, cancel) } continue } @@ -262,7 +270,7 @@ func (s *handlerConnectProxy) handleUpdate(ctx context.Context, u UpdateEvent, s } peer := strings.TrimPrefix(u.CorrelationID, peerTrustBundleIDPrefix) if resp.Bundle != nil { - snap.ConnectProxy.UpstreamPeerTrustBundles[peer] = resp.Bundle + snap.ConnectProxy.UpstreamPeerTrustBundles.Set(peer, resp.Bundle) } case u.CorrelationID == peeringTrustBundlesWatchID: @@ -283,6 +291,90 @@ func (s *handlerConnectProxy) handleUpdate(ctx context.Context, u UpdateEvent, s snap.ConnectProxy.Intentions = resp snap.ConnectProxy.IntentionsSet = true + case u.CorrelationID == peeredUpstreamsID: + resp, ok := u.Result.(*structs.IndexedPeeredServiceList) + if !ok { + return fmt.Errorf("invalid type for response %T", u.Result) + } + + seenUpstreams := make(map[UpstreamID]struct{}) + for _, psn := range resp.Services { + uid := NewUpstreamIDFromPeeredServiceName(psn) + + if _, ok := seenUpstreams[uid]; ok { + continue + } + seenUpstreams[uid] = struct{}{} + + s.logger.Trace("initializing watch of peered upstream", "upstream", uid) + + hctx, hcancel := context.WithCancel(ctx) + err := s.dataSources.Health.Notify(hctx, &structs.ServiceSpecificRequest{ + PeerName: uid.Peer, + Datacenter: s.source.Datacenter, + QueryOptions: structs.QueryOptions{ + Token: s.token, + }, + ServiceName: psn.ServiceName.Name, + Connect: true, + // Note that Identifier doesn't type-prefix for service any more as it's + // the default and makes metrics and other things much cleaner. It's + // simpler for us if we have the type to make things unambiguous. + Source: *s.source, + EnterpriseMeta: uid.EnterpriseMeta, + }, upstreamPeerWatchIDPrefix+uid.String(), s.ch) + if err != nil { + hcancel() + return fmt.Errorf("failed to watch health for %s: %v", uid, err) + } + snap.ConnectProxy.PeerUpstreamEndpoints.InitWatch(uid, hcancel) + + // Check whether a watch for this peer exists to avoid duplicates. + if _, ok := snap.ConnectProxy.UpstreamPeerTrustBundles.Get(uid.Peer); !ok { + peerCtx, cancel := context.WithCancel(ctx) + if err := s.dataSources.TrustBundle.Notify(peerCtx, &pbpeering.TrustBundleReadRequest{ + Name: uid.Peer, + Partition: uid.PartitionOrDefault(), + }, peerTrustBundleIDPrefix+uid.Peer, s.ch); err != nil { + cancel() + return fmt.Errorf("error while watching trust bundle for peer %q: %w", uid.Peer, err) + } + + snap.ConnectProxy.UpstreamPeerTrustBundles.InitWatch(uid.Peer, cancel) + } + } + snap.ConnectProxy.PeeredUpstreams = seenUpstreams + + // + // Clean up data + // + + validPeerNames := make(map[string]struct{}) + + // Iterate through all known endpoints and remove references to upstream IDs that weren't in the update + snap.ConnectProxy.PeerUpstreamEndpoints.ForEachKey(func(uid UpstreamID) bool { + // Peered upstream is explicitly defined in upstream config + if _, ok := snap.ConnectProxy.UpstreamConfig[uid]; ok { + validPeerNames[uid.Peer] = struct{}{} + return true + } + // Peered upstream came from dynamic source of imported services + if _, ok := seenUpstreams[uid]; ok { + validPeerNames[uid.Peer] = struct{}{} + return true + } + snap.ConnectProxy.PeerUpstreamEndpoints.CancelWatch(uid) + return true + }) + + // Iterate through all known trust bundles and remove references to any unseen peer names + snap.ConnectProxy.UpstreamPeerTrustBundles.ForEachKey(func(peerName PeerName) bool { + if _, ok := validPeerNames[peerName]; !ok { + snap.ConnectProxy.UpstreamPeerTrustBundles.CancelWatch(peerName) + } + return true + }) + case u.CorrelationID == intentionUpstreamsID: resp, ok := u.Result.(*structs.IndexedServiceList) if !ok { diff --git a/agent/proxycfg/data_sources.go b/agent/proxycfg/data_sources.go index 73c8b06375..310a4340ea 100644 --- a/agent/proxycfg/data_sources.go +++ b/agent/proxycfg/data_sources.go @@ -69,6 +69,8 @@ type DataSources struct { // notification channel. LeafCertificate LeafCertificate + // PeeredUpstreams provides imported-service upstream updates on a + // notification channel. PeeredUpstreams PeeredUpstreams // PreparedQuery provides updates about the results of a prepared query. diff --git a/agent/proxycfg/internal/watch/watchmap.go b/agent/proxycfg/internal/watch/watchmap.go new file mode 100644 index 0000000000..bbf42dc9af --- /dev/null +++ b/agent/proxycfg/internal/watch/watchmap.go @@ -0,0 +1,108 @@ +package watch + +import "context" + +// Map safely stores and retrieves values by validating that +// there is a live watch for a key. InitWatch must be called +// to associate a key with its cancel function before any +// Set's are called. +type Map[K comparable, V any] struct { + M map[K]watchedVal[V] +} + +type watchedVal[V any] struct { + Val *V + + // keeping cancel private has a beneficial side effect: + // copying Map with copystructure.Copy will zero out + // cancel, preventing it from being called by the + // receiver of a proxy config snapshot. + cancel context.CancelFunc +} + +func NewMap[K comparable, V any]() Map[K, V] { + return Map[K, V]{M: make(map[K]watchedVal[V])} +} + +// InitWatch associates a cancel function with a key, +// allowing Set to be called for the key. The cancel +// function is allowed to be nil. +// +// Any existing data for a key will be cancelled and +// overwritten. +func (m Map[K, V]) InitWatch(key K, cancel func()) { + if _, present := m.M[key]; present { + m.CancelWatch(key) + } + m.M[key] = watchedVal[V]{ + cancel: cancel, + } +} + +// CancelWatch first calls the cancel function +// associated with the key then deletes the key +// from the map. No-op if key is not present. +func (m Map[K, V]) CancelWatch(key K) { + if entry, ok := m.M[key]; ok { + if entry.cancel != nil { + entry.cancel() + } + delete(m.M, key) + } +} + +// IsWatched returns true if InitWatch has been +// called for key and has not been cancelled by +// CancelWatch. +func (m Map[K, V]) IsWatched(key K) bool { + if _, present := m.M[key]; present { + return true + } + return false +} + +// Set stores V if K exists in the map. +// No-op if the key never was initialized with InitWatch +// or if the entry got cancelled by CancelWatch. +func (m Map[K, V]) Set(key K, val V) bool { + if entry, ok := m.M[key]; ok { + entry.Val = &val + m.M[key] = entry + return true + } + return false +} + +// Get returns the underlying value for a key. +// If an entry has been set, returns (V, true). +// Otherwise, returns the zero value (V, false). +// +// Note that even if InitWatch has been called +// for a key, unless Set has been called this +// function will return false. +func (m Map[K, V]) Get(key K) (V, bool) { + if entry, ok := m.M[key]; ok { + if entry.Val != nil { + return *entry.Val, true + } + } + var empty V + return empty, false +} + +func (m Map[K, V]) Len() int { + return len(m.M) +} + +// ForEachKey iterates through the map, calling f +// for each iteration. It is up to the caller to +// Get the value and nil-check if required. +// Stops iterating if f returns false. +// Order of iteration is non-deterministic. +func (m Map[K, V]) ForEachKey(f func(K) bool) { + for k := range m.M { + if ok := f(k); !ok { + return + } + } +} diff --git a/agent/proxycfg/internal/watch/watchmap_test.go b/agent/proxycfg/internal/watch/watchmap_test.go new file mode 100644 index 0000000000..590351853e --- /dev/null +++ b/agent/proxycfg/internal/watch/watchmap_test.go @@ -0,0 +1,113 @@ +package watch + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestMap(t *testing.T) { + m := NewMap[string, string]() + + // Set without init is a no-op + { + m.Set("hello", "world") + require.Equal(t, 0, m.Len()) + } + + // Getting from empty map + { + got, ok := m.Get("hello") + require.False(t, ok) + require.Empty(t, got) + } + + var called bool + cancelMock := func() { + called = true + } + + // InitWatch successful + { + m.InitWatch("hello", cancelMock) + require.Equal(t, 1, m.Len()) + } + + // Get still returns false + { + got, ok := m.Get("hello") + require.False(t, ok) + require.Empty(t, got) + } + + // Set successful + { + require.True(t, m.Set("hello", "world")) + require.Equal(t, 1, m.Len()) + } + + // Get successful + { + got, ok := m.Get("hello") + require.True(t, ok) + require.Equal(t, "world", got) + } + + // CancelWatch successful + { + m.CancelWatch("hello") + require.Equal(t, 0, m.Len()) + require.True(t, called) + } + + // Get no-op + { + got, ok := m.Get("hello") + require.False(t, ok) + require.Empty(t, got) + } + + // Set no-op + { + require.False(t, m.Set("hello", "world")) + require.Equal(t, 0, m.Len()) + } +} + +func TestMap_ForEach(t *testing.T) { + type testType struct { + s string + } + + m := NewMap[string, any]() + inputs := map[string]any{ + "hello": 13, + "foo": struct{}{}, + "bar": &testType{s: "wow"}, + } + for k, v := range inputs { + m.InitWatch(k, nil) + m.Set(k, v) + } + require.Equal(t, 3, m.Len()) + + // returning true continues iteration + { + var count int + m.ForEachKey(func(k string) bool { + count++ + return true + }) + require.Equal(t, 3, count) + } + + // returning false exits loop + { + var count int + m.ForEachKey(func(k string) bool { + count++ + return false + }) + require.Equal(t, 1, count) + } +} diff --git a/agent/proxycfg/manager_test.go b/agent/proxycfg/manager_test.go index 12d8c79194..184b62148f 100644 --- a/agent/proxycfg/manager_test.go +++ b/agent/proxycfg/manager_test.go @@ -11,6 +11,7 @@ import ( cachetype "github.com/hashicorp/consul/agent/cache-types" "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/discoverychain" + "github.com/hashicorp/consul/agent/proxycfg/internal/watch" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/proto/pbpeering" @@ -230,8 +231,8 @@ func TestManager_BasicLifecycle(t *testing.T) { }, PassthroughUpstreams: map[UpstreamID]map[string]map[string]struct{}{}, PassthroughIndices: map[string]indexedTarget{}, - UpstreamPeerTrustBundles: map[string]*pbpeering.PeeringTrustBundle{}, - PeerUpstreamEndpoints: map[UpstreamID]structs.CheckServiceNodes{}, + UpstreamPeerTrustBundles: watch.NewMap[PeerName, *pbpeering.PeeringTrustBundle](), + PeerUpstreamEndpoints: watch.NewMap[UpstreamID, structs.CheckServiceNodes](), PeerUpstreamEndpointsUseHostnames: map[UpstreamID]struct{}{}, }, PreparedQueryEndpoints: map[UpstreamID]structs.CheckServiceNodes{}, @@ -291,8 +292,8 @@ func TestManager_BasicLifecycle(t *testing.T) { }, PassthroughUpstreams: map[UpstreamID]map[string]map[string]struct{}{}, PassthroughIndices: map[string]indexedTarget{}, - UpstreamPeerTrustBundles: map[string]*pbpeering.PeeringTrustBundle{}, - PeerUpstreamEndpoints: map[UpstreamID]structs.CheckServiceNodes{}, + UpstreamPeerTrustBundles: watch.NewMap[PeerName, *pbpeering.PeeringTrustBundle](), + PeerUpstreamEndpoints: watch.NewMap[UpstreamID, structs.CheckServiceNodes](), PeerUpstreamEndpointsUseHostnames: map[UpstreamID]struct{}{}, }, PreparedQueryEndpoints: map[UpstreamID]structs.CheckServiceNodes{}, diff --git a/agent/proxycfg/naming.go b/agent/proxycfg/naming.go index 7b80d49a9d..3bb0854b04 100644 --- a/agent/proxycfg/naming.go +++ b/agent/proxycfg/naming.go @@ -7,6 +7,8 @@ import ( "github.com/hashicorp/consul/agent/structs" ) +type PeerName = string + type UpstreamID struct { Type string Name string @@ -32,7 +34,16 @@ func NewUpstreamID(u *structs.Upstream) UpstreamID { return id } -// TODO(peering): confirm we don't need peername here +func NewUpstreamIDFromPeeredServiceName(psn structs.PeeredServiceName) UpstreamID { + id := UpstreamID{ + Name: psn.ServiceName.Name, + EnterpriseMeta: psn.ServiceName.EnterpriseMeta, + Peer: psn.Peer, + } + id.normalize() + return id +} + func NewUpstreamIDFromServiceName(sn structs.ServiceName) UpstreamID { id := UpstreamID{ Name: sn.Name, diff --git a/agent/proxycfg/snapshot.go b/agent/proxycfg/snapshot.go index c52a99a811..6a02aad1e6 100644 --- a/agent/proxycfg/snapshot.go +++ b/agent/proxycfg/snapshot.go @@ -9,6 +9,7 @@ import ( "github.com/mitchellh/copystructure" "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/proxycfg/internal/watch" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/proto/pbpeering" @@ -44,13 +45,9 @@ type ConfigSnapshotUpstreams struct { // endpoints of an upstream. WatchedUpstreamEndpoints map[UpstreamID]map[string]structs.CheckServiceNodes - // WatchedUpstreamPeerTrustBundles is a map of (PeerName -> CancelFunc) in order to cancel - // watches for peer trust bundles any time the list of upstream peers changes. - WatchedUpstreamPeerTrustBundles map[string]context.CancelFunc - // UpstreamPeerTrustBundles is a map of (PeerName -> PeeringTrustBundle). // It is used to store trust bundles for upstream TLS transport sockets. - UpstreamPeerTrustBundles map[string]*pbpeering.PeeringTrustBundle + UpstreamPeerTrustBundles watch.Map[PeerName, *pbpeering.PeeringTrustBundle] // WatchedGateways is a map of UpstreamID -> (map of GatewayKey.String() -> // CancelFunc) in order to cancel watches for mesh gateways @@ -80,10 +77,16 @@ type ConfigSnapshotUpstreams struct { // This list only applies to proxies registered in 'transparent' mode. IntentionUpstreams map[UpstreamID]struct{} + // PeeredUpstreams is a set of all upstream targets in a local partition. + // + // This list only applies to proxies registered in 'transparent' mode. + PeeredUpstreams map[UpstreamID]struct{} + // PeerUpstreamEndpoints is a map of UpstreamID -> (set of IP addresses) // and used to determine the backing endpoints of an upstream in another // peer. - PeerUpstreamEndpoints map[UpstreamID]structs.CheckServiceNodes + PeerUpstreamEndpoints watch.Map[UpstreamID, structs.CheckServiceNodes] + PeerUpstreamEndpointsUseHostnames map[UpstreamID]struct{} } @@ -152,8 +155,7 @@ func (c *configSnapshotConnectProxy) isEmpty() bool { len(c.WatchedDiscoveryChains) == 0 && len(c.WatchedUpstreams) == 0 && len(c.WatchedUpstreamEndpoints) == 0 && - len(c.WatchedUpstreamPeerTrustBundles) == 0 && - len(c.UpstreamPeerTrustBundles) == 0 && + c.UpstreamPeerTrustBundles.Len() == 0 && len(c.WatchedGateways) == 0 && len(c.WatchedGatewayEndpoints) == 0 && len(c.WatchedServiceChecks) == 0 && @@ -161,12 +163,19 @@ func (c *configSnapshotConnectProxy) isEmpty() bool { len(c.UpstreamConfig) == 0 && len(c.PassthroughUpstreams) == 0 && len(c.IntentionUpstreams) == 0 && + len(c.PeeredUpstreams) == 0 && !c.InboundPeerTrustBundlesSet && !c.MeshConfigSet && - len(c.PeerUpstreamEndpoints) == 0 && + c.PeerUpstreamEndpoints.Len() == 0 && len(c.PeerUpstreamEndpointsUseHostnames) == 0 } +func (c *configSnapshotConnectProxy) IsImplicitUpstream(uid UpstreamID) bool { + _, intentionImplicit := c.IntentionUpstreams[uid] + _, peeringImplicit := c.PeeredUpstreams[uid] + return intentionImplicit || peeringImplicit +} + type configSnapshotTerminatingGateway struct { MeshConfig *structs.MeshConfigEntry MeshConfigSet bool @@ -715,7 +724,6 @@ func (s *ConfigSnapshot) Clone() (*ConfigSnapshot, error) { snap.ConnectProxy.WatchedUpstreams = nil snap.ConnectProxy.WatchedGateways = nil snap.ConnectProxy.WatchedDiscoveryChains = nil - snap.ConnectProxy.WatchedUpstreamPeerTrustBundles = nil case structs.ServiceKindTerminatingGateway: snap.TerminatingGateway.WatchedServices = nil snap.TerminatingGateway.WatchedIntentions = nil @@ -730,7 +738,6 @@ func (s *ConfigSnapshot) Clone() (*ConfigSnapshot, error) { snap.IngressGateway.WatchedUpstreams = nil snap.IngressGateway.WatchedGateways = nil snap.IngressGateway.WatchedDiscoveryChains = nil - snap.IngressGateway.WatchedUpstreamPeerTrustBundles = nil // only ingress-gateway snap.IngressGateway.LeafCertWatchCancel = nil } @@ -803,7 +810,7 @@ func (s *ConfigSnapshot) MeshConfigTLSOutgoing() *structs.MeshDirectionalTLSConf } func (u *ConfigSnapshotUpstreams) UpstreamPeerMeta(uid UpstreamID) structs.PeeringServiceMeta { - nodes := u.PeerUpstreamEndpoints[uid] + nodes, _ := u.PeerUpstreamEndpoints.Get(uid) if len(nodes) == 0 { return structs.PeeringServiceMeta{} } @@ -833,7 +840,7 @@ func (u *ConfigSnapshotUpstreams) PeeredUpstreamIDs() []UpstreamID { continue } - if _, ok := u.UpstreamPeerTrustBundles[uid.Peer]; uid.Peer != "" && !ok { + if _, ok := u.UpstreamPeerTrustBundles.Get(uid.Peer); !ok { // The trust bundle for this upstream is not available yet, skip for now. continue } diff --git a/agent/proxycfg/state.go b/agent/proxycfg/state.go index 9fc5c88f66..f9388cf487 100644 --- a/agent/proxycfg/state.go +++ b/agent/proxycfg/state.go @@ -36,6 +36,7 @@ const ( serviceResolverIDPrefix = "service-resolver:" serviceIntentionsIDPrefix = "service-intentions:" intentionUpstreamsID = "intention-upstreams" + peeredUpstreamsID = "peered-upstreams" upstreamPeerWatchIDPrefix = "upstream-peer:" exportedServiceListWatchID = "exported-service-list" meshConfigEntryID = "mesh" diff --git a/agent/proxycfg/state_test.go b/agent/proxycfg/state_test.go index 3a54d0314f..36b641a691 100644 --- a/agent/proxycfg/state_test.go +++ b/agent/proxycfg/state_test.go @@ -131,6 +131,7 @@ func recordWatches(sc *stateConfig) *watchRecorder { IntentionUpstreams: typedWatchRecorder[*structs.ServiceSpecificRequest]{wr}, InternalServiceDump: typedWatchRecorder[*structs.ServiceDumpRequest]{wr}, LeafCertificate: typedWatchRecorder[*cachetype.ConnectCALeafRequest]{wr}, + PeeredUpstreams: typedWatchRecorder[*structs.PartitionSpecificRequest]{wr}, PreparedQuery: typedWatchRecorder[*structs.PreparedQueryExecuteRequest]{wr}, ResolvedServiceConfig: typedWatchRecorder[*structs.ServiceConfigRequest]{wr}, ServiceList: typedWatchRecorder[*structs.DCSpecificRequest]{wr}, @@ -321,6 +322,15 @@ func genVerifyServiceSpecificPeeredRequest(expectedService, expectedFilter, expe } } +func genVerifyPartitionSpecificRequest(expectedPartition, expectedDatacenter string) verifyWatchRequest { + return func(t testing.TB, request any) { + reqReal, ok := request.(*structs.PartitionSpecificRequest) + require.True(t, ok) + require.Equal(t, expectedDatacenter, reqReal.Datacenter) + require.Equal(t, expectedPartition, reqReal.PartitionOrDefault()) + } +} + func genVerifyGatewayServiceWatch(expectedService, expectedDatacenter string) verifyWatchRequest { return genVerifyServiceSpecificRequest(expectedService, "", expectedDatacenter, false) } @@ -404,9 +414,11 @@ func TestState_WatchesAndUpdates(t *testing.T) { dbUID = NewUpstreamIDFromServiceName(db) pqUID = UpstreamIDFromString("prepared_query:query") extApiUID = NewUpstreamIDFromServiceName(apiA) + extDBUID = NewUpstreamIDFromServiceName(db) ) // TODO(peering): NewUpstreamIDFromServiceName should take a PeerName extApiUID.Peer = "peer-a" + extDBUID.Peer = "peer-a" const peerTrustDomain = "1c053652-8512-4373-90cf-5a7f6263a994.consul" @@ -2509,6 +2521,253 @@ func TestState_WatchesAndUpdates(t *testing.T) { }, }, }, + "transparent-proxy-initial-with-peers": { + ns: structs.NodeService{ + Kind: structs.ServiceKindConnectProxy, + ID: "api-proxy", + Service: "api-proxy", + Address: "10.0.1.1", + Proxy: structs.ConnectProxyConfig{ + DestinationServiceName: "api", + Mode: structs.ProxyModeTransparent, + Upstreams: structs.Upstreams{ + { + DestinationName: "api-a", + DestinationPeer: "peer-a", + }, + }, + }, + }, + sourceDC: "dc1", + stages: []verificationStage{ + { + requiredWatches: map[string]verifyWatchRequest{ + peeringTrustBundlesWatchID: genVerifyTrustBundleListWatch("api"), + peeredUpstreamsID: genVerifyPartitionSpecificRequest(acl.DefaultEnterpriseMeta().PartitionOrDefault(), "dc1"), + meshConfigEntryID: genVerifyMeshConfigWatch("dc1"), + rootsWatchID: genVerifyDCSpecificWatch("dc1"), + leafWatchID: genVerifyLeafWatch("api", "dc1"), + }, + verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) { + require.False(t, snap.Valid(), "proxy without roots/leaf/intentions is not valid") + require.True(t, snap.MeshGateway.isEmpty()) + require.True(t, snap.IngressGateway.isEmpty()) + require.True(t, snap.TerminatingGateway.isEmpty()) + + require.False(t, snap.ConnectProxy.isEmpty()) + + // This is explicitly defined from proxy config + expectUpstreams := map[UpstreamID]*structs.Upstream{ + extApiUID: { + DestinationName: "api-a", + DestinationNamespace: structs.IntentionDefaultNamespace, + DestinationPartition: structs.IntentionDefaultNamespace, + DestinationPeer: "peer-a", + }, + } + require.Equal(t, expectUpstreams, snap.ConnectProxy.UpstreamConfig) + }, + }, + { + // Initial events + events: []UpdateEvent{ + rootWatchEvent(), + { + CorrelationID: leafWatchID, + Result: issuedCert, + Err: nil, + }, + { + CorrelationID: intentionsWatchID, + Result: TestIntentions(), + Err: nil, + }, + { + CorrelationID: peeringTrustBundlesWatchID, + Result: peerTrustBundles, + }, + { + CorrelationID: peeredUpstreamsID, + Result: &structs.IndexedPeeredServiceList{ + Services: []structs.PeeredServiceName{ + { + ServiceName: apiA, + Peer: "peer-a", + }, + { + // This service is dynamic (not from static config) + ServiceName: db, + Peer: "peer-a", + }, + }, + }, + }, + { + CorrelationID: meshConfigEntryID, + Result: &structs.ConfigEntryResponse{ + Entry: nil, // no explicit config + }, + Err: nil, + }, + }, + verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) { + require.True(t, snap.Valid(), "proxy with roots/leaf/intentions is valid") + require.Equal(t, indexedRoots, snap.Roots) + require.Equal(t, issuedCert, snap.Leaf()) + require.True(t, snap.MeshGateway.isEmpty()) + require.True(t, snap.IngressGateway.isEmpty()) + require.True(t, snap.TerminatingGateway.isEmpty()) + require.True(t, snap.ConnectProxy.MeshConfigSet) + require.Nil(t, snap.ConnectProxy.MeshConfig) + + // Check PeeredUpstream is populated + expect := map[UpstreamID]struct{}{ + extDBUID: {}, + extApiUID: {}, + } + require.Equal(t, expect, snap.ConnectProxy.PeeredUpstreams) + + require.True(t, snap.ConnectProxy.PeerUpstreamEndpoints.IsWatched(extApiUID)) + _, ok := snap.ConnectProxy.PeerUpstreamEndpoints.Get(extApiUID) + require.False(t, ok, "expected initialized but empty PeerUpstreamEndpoint") + + require.True(t, snap.ConnectProxy.PeerUpstreamEndpoints.IsWatched(extDBUID)) + _, ok = snap.ConnectProxy.PeerUpstreamEndpoints.Get(extDBUID) + require.False(t, ok, "expected initialized but empty PeerUpstreamEndpoint") + + require.True(t, snap.ConnectProxy.UpstreamPeerTrustBundles.IsWatched("peer-a")) + _, ok = snap.ConnectProxy.UpstreamPeerTrustBundles.Get("peer-a") + require.False(t, ok, "expected initialized but empty PeerTrustBundle") + }, + }, + { + // Peered upstream will have set up 3 more watches + requiredWatches: map[string]verifyWatchRequest{ + upstreamPeerWatchIDPrefix + extApiUID.String(): genVerifyServiceSpecificPeeredRequest("api-a", "", "dc1", "peer-a", true), + upstreamPeerWatchIDPrefix + extDBUID.String(): genVerifyServiceSpecificPeeredRequest("db", "", "dc1", "peer-a", true), + peerTrustBundleIDPrefix + "peer-a": genVerifyTrustBundleReadWatch("peer-a"), + }, + events: []UpdateEvent{ + { + CorrelationID: peerTrustBundleIDPrefix + "peer-a", + Result: &pbpeering.TrustBundleReadResponse{ + Bundle: peerTrustBundles.Bundles[0], + }, + }, + }, + verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) { + require.True(t, snap.Valid(), "proxy with roots/leaf/intentions is valid") + require.Equal(t, indexedRoots, snap.Roots) + require.Equal(t, issuedCert, snap.Leaf()) + require.True(t, snap.MeshGateway.isEmpty()) + require.True(t, snap.IngressGateway.isEmpty()) + require.True(t, snap.TerminatingGateway.isEmpty()) + require.True(t, snap.ConnectProxy.MeshConfigSet) + require.Nil(t, snap.ConnectProxy.MeshConfig) + + // Check PeeredUpstream is populated + expect := map[UpstreamID]struct{}{ + extDBUID: {}, + extApiUID: {}, + } + require.Equal(t, expect, snap.ConnectProxy.PeeredUpstreams) + + // Expect two entries (DB and api-a) + require.Equal(t, 2, snap.ConnectProxy.PeerUpstreamEndpoints.Len()) + + // db does not have endpoints yet + ep, _ := snap.ConnectProxy.PeerUpstreamEndpoints.Get(extDBUID) + require.Nil(t, ep) + + // Expect a trust bundle + ptb, ok := snap.ConnectProxy.UpstreamPeerTrustBundles.Get("peer-a") + require.True(t, ok) + prototest.AssertDeepEqual(t, peerTrustBundles.Bundles[0], ptb) + + // Sanity check that local upstream maps are not populated + require.Empty(t, snap.ConnectProxy.WatchedUpstreamEndpoints[extDBUID]) + require.Empty(t, snap.ConnectProxy.PassthroughUpstreams[extDBUID]) + require.Empty(t, snap.ConnectProxy.PassthroughIndices) + }, + }, + { + // Add another instance of "api-a" service + events: []UpdateEvent{ + { + CorrelationID: upstreamPeerWatchIDPrefix + extDBUID.String(), + Result: &structs.IndexedCheckServiceNodes{ + Nodes: structs.CheckServiceNodes{ + { + Node: &structs.Node{ + Node: "node1", + Address: "127.0.0.1", + PeerName: "peer-a", + }, + Service: &structs.NodeService{ + ID: "db", + Service: "db", + PeerName: "peer-a", + Connect: structs.ServiceConnect{}, + }, + }, + }, + }, + }, + }, + verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) { + require.True(t, snap.Valid(), "proxy with roots/leaf/intentions is valid") + + // Check PeeredUpstream is populated + expect := map[UpstreamID]struct{}{ + extApiUID: {}, + extDBUID: {}, + } + require.Equal(t, expect, snap.ConnectProxy.PeeredUpstreams) + + // Expect two entries (api-a, db) + require.Equal(t, 2, snap.ConnectProxy.PeerUpstreamEndpoints.Len()) + + // db has an endpoint now + ep, _ := snap.ConnectProxy.PeerUpstreamEndpoints.Get(extDBUID) + require.NotNil(t, ep) + require.Len(t, ep, 1) + + // Expect a trust bundle + ptb, ok := snap.ConnectProxy.UpstreamPeerTrustBundles.Get("peer-a") + require.True(t, ok) + prototest.AssertDeepEqual(t, peerTrustBundles.Bundles[0], ptb) + + // Sanity check that local upstream maps are not populated + require.Empty(t, snap.ConnectProxy.WatchedUpstreamEndpoints[extDBUID]) + require.Empty(t, snap.ConnectProxy.PassthroughUpstreams[extDBUID]) + require.Empty(t, snap.ConnectProxy.PassthroughIndices) + }, + }, + { + // Empty list of peered upstreams should clean up map keys + events: []UpdateEvent{ + { + CorrelationID: peeredUpstreamsID, + Result: &structs.IndexedPeeredServiceList{ + Services: []structs.PeeredServiceName{}, + }, + }, + }, + verifySnapshot: func(t testing.TB, snap *ConfigSnapshot) { + require.True(t, snap.Valid(), "proxy with roots/leaf/intentions is valid") + + require.Empty(t, snap.ConnectProxy.PeeredUpstreams) + + // db endpoint should have been cleaned up + require.False(t, snap.ConnectProxy.PeerUpstreamEndpoints.IsWatched(extDBUID)) + + // Expect only api-a endpoint + require.Equal(t, 1, snap.ConnectProxy.PeerUpstreamEndpoints.Len()) + require.Equal(t, 1, snap.ConnectProxy.UpstreamPeerTrustBundles.Len()) + }, + }, + }, + }, "connect-proxy": newConnectProxyCase(structs.MeshGatewayModeDefault), "connect-proxy-mesh-gateway-local": newConnectProxyCase(structs.MeshGatewayModeLocal), "connect-proxy-with-peers": { @@ -2564,10 +2823,15 @@ func TestState_WatchesAndUpdates(t *testing.T) { require.Len(t, snap.ConnectProxy.WatchedGateways, 0, "%+v", snap.ConnectProxy.WatchedGateways) require.Len(t, snap.ConnectProxy.WatchedGatewayEndpoints, 0, "%+v", snap.ConnectProxy.WatchedGatewayEndpoints) - require.Contains(t, snap.ConnectProxy.WatchedUpstreamPeerTrustBundles, "peer-a", "%+v", snap.ConnectProxy.WatchedUpstreamPeerTrustBundles) - require.Len(t, snap.ConnectProxy.UpstreamPeerTrustBundles, 0, "%+v", snap.ConnectProxy.UpstreamPeerTrustBundles) + // watch initialized + require.True(t, snap.ConnectProxy.UpstreamPeerTrustBundles.IsWatched("peer-a")) + _, ok := snap.ConnectProxy.UpstreamPeerTrustBundles.Get("peer-a") + require.False(t, ok) // but no data - require.Len(t, snap.ConnectProxy.PeerUpstreamEndpoints, 0, "%+v", snap.ConnectProxy.PeerUpstreamEndpoints) + // watch initialized + require.True(t, snap.ConnectProxy.PeerUpstreamEndpoints.IsWatched(extApiUID)) + _, ok = snap.ConnectProxy.PeerUpstreamEndpoints.Get(extApiUID) + require.False(t, ok) // but no data require.Len(t, snap.ConnectProxy.WatchedServiceChecks, 0, "%+v", snap.ConnectProxy.WatchedServiceChecks) require.Len(t, snap.ConnectProxy.PreparedQueryEndpoints, 0, "%+v", snap.ConnectProxy.PreparedQueryEndpoints) @@ -2655,11 +2919,13 @@ func TestState_WatchesAndUpdates(t *testing.T) { require.Len(t, snap.ConnectProxy.WatchedGateways, 1, "%+v", snap.ConnectProxy.WatchedGateways) require.Len(t, snap.ConnectProxy.WatchedGatewayEndpoints, 1, "%+v", snap.ConnectProxy.WatchedGatewayEndpoints) - require.Contains(t, snap.ConnectProxy.WatchedUpstreamPeerTrustBundles, "peer-a", "%+v", snap.ConnectProxy.WatchedUpstreamPeerTrustBundles) - require.Equal(t, peerTrustBundles.Bundles[0], snap.ConnectProxy.UpstreamPeerTrustBundles["peer-a"], "%+v", snap.ConnectProxy.WatchedUpstreamPeerTrustBundles) + tb, ok := snap.ConnectProxy.UpstreamPeerTrustBundles.Get("peer-a") + require.True(t, ok) + prototest.AssertDeepEqual(t, peerTrustBundles.Bundles[0], tb) - require.Len(t, snap.ConnectProxy.PeerUpstreamEndpoints, 1, "%+v", snap.ConnectProxy.PeerUpstreamEndpoints) - require.NotNil(t, snap.ConnectProxy.PeerUpstreamEndpoints[extApiUID]) + require.Equal(t, 1, snap.ConnectProxy.PeerUpstreamEndpoints.Len()) + ep, _ := snap.ConnectProxy.PeerUpstreamEndpoints.Get(extApiUID) + require.NotNil(t, ep) require.Len(t, snap.ConnectProxy.WatchedServiceChecks, 0, "%+v", snap.ConnectProxy.WatchedServiceChecks) require.Len(t, snap.ConnectProxy.PreparedQueryEndpoints, 0, "%+v", snap.ConnectProxy.PreparedQueryEndpoints) diff --git a/agent/proxycfg/testing.go b/agent/proxycfg/testing.go index c30435e374..744c17e182 100644 --- a/agent/proxycfg/testing.go +++ b/agent/proxycfg/testing.go @@ -745,6 +745,7 @@ func testConfigSnapshotFixture( IntentionUpstreams: &noopDataSource[*structs.ServiceSpecificRequest]{}, InternalServiceDump: &noopDataSource[*structs.ServiceDumpRequest]{}, LeafCertificate: &noopDataSource[*cachetype.ConnectCALeafRequest]{}, + PeeredUpstreams: &noopDataSource[*structs.PartitionSpecificRequest]{}, PreparedQuery: &noopDataSource[*structs.PreparedQueryExecuteRequest]{}, ResolvedServiceConfig: &noopDataSource[*structs.ServiceConfigRequest]{}, ServiceList: &noopDataSource[*structs.DCSpecificRequest]{}, @@ -971,6 +972,7 @@ type TestDataSources struct { IntentionUpstreams *TestDataSource[*structs.ServiceSpecificRequest, *structs.IndexedServiceList] InternalServiceDump *TestDataSource[*structs.ServiceDumpRequest, *structs.IndexedNodesWithGateways] LeafCertificate *TestDataSource[*cachetype.ConnectCALeafRequest, *structs.IssuedCert] + PeeredUpstreams *TestDataSource[*structs.PartitionSpecificRequest, *structs.IndexedPeeredServiceList] PreparedQuery *TestDataSource[*structs.PreparedQueryExecuteRequest, *structs.PreparedQueryExecuteResponse] ResolvedServiceConfig *TestDataSource[*structs.ServiceConfigRequest, *structs.ServiceConfigResponse] ServiceList *TestDataSource[*structs.DCSpecificRequest, *structs.IndexedServiceList] @@ -994,6 +996,7 @@ func (t *TestDataSources) ToDataSources() DataSources { IntentionUpstreams: t.IntentionUpstreams, InternalServiceDump: t.InternalServiceDump, LeafCertificate: t.LeafCertificate, + PeeredUpstreams: t.PeeredUpstreams, PreparedQuery: t.PreparedQuery, ResolvedServiceConfig: t.ResolvedServiceConfig, ServiceList: t.ServiceList, diff --git a/agent/proxycfg/testing_mesh_gateway.go b/agent/proxycfg/testing_mesh_gateway.go index 2c81d85fef..388ac12b82 100644 --- a/agent/proxycfg/testing_mesh_gateway.go +++ b/agent/proxycfg/testing_mesh_gateway.go @@ -548,10 +548,19 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( }, &structs.ServiceResolverConfigEntry{ Kind: structs.ServiceResolver, - Name: "api-dc2", + Name: "api", + Subsets: map[string]structs.ServiceResolverSubset{ + "v2": { + Filter: "Service.Meta.version == v2", + }, + }, + }, + &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "api-v2", Redirect: &structs.ServiceResolverRedirect{ - Service: "api", - Datacenter: "dc2", + Service: "api", + ServiceSubset: "v2", }, }, &structs.ServiceSplitterConfigEntry{ @@ -576,7 +585,7 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( Match: httpMatch(&structs.ServiceRouteHTTPMatch{ PathPrefix: "/api", }), - Destination: toService("api-dc2"), + Destination: toService("api-v2"), }, }, }, @@ -602,13 +611,7 @@ func TestConfigSnapshotPeeredMeshGateway(t testing.T, variant string, nsFn func( extraUpdates = append(extraUpdates, UpdateEvent{ CorrelationID: datacentersWatchID, - Result: &[]string{"dc1", "dc2"}, - }, - UpdateEvent{ - CorrelationID: "mesh-gateway:dc2", - Result: &structs.IndexedNodesWithGateways{ - Nodes: TestGatewayNodesDC2(t), - }, + Result: &[]string{"dc1"}, }, UpdateEvent{ CorrelationID: exportedServiceListWatchID, diff --git a/agent/proxycfg/testing_terminating_gateway.go b/agent/proxycfg/testing_terminating_gateway.go index bac411fff8..00771433b5 100644 --- a/agent/proxycfg/testing_terminating_gateway.go +++ b/agent/proxycfg/testing_terminating_gateway.go @@ -633,6 +633,123 @@ func TestConfigSnapshotTerminatingGatewaySNI(t testing.T) *ConfigSnapshot { }) } +func TestConfigSnapshotTerminatingGatewayHTTP2(t testing.T) *ConfigSnapshot { + web := structs.NewServiceName("web", nil) + + return TestConfigSnapshotTerminatingGateway(t, false, nil, []UpdateEvent{ + { + CorrelationID: gatewayServicesWatchID, + Result: &structs.IndexedGatewayServices{ + Services: []*structs.GatewayService{ + { + Service: web, + CAFile: "ca.cert.pem", + }, + }, + }, + }, + { + CorrelationID: serviceConfigIDPrefix + web.String(), + Result: &structs.ServiceConfigResponse{ + ProxyConfig: map[string]interface{}{"protocol": "http2"}, + }, + }, + { + CorrelationID: externalServiceIDPrefix + web.String(), + Result: &structs.IndexedCheckServiceNodes{ + Nodes: []structs.CheckServiceNode{ + { + Node: &structs.Node{ + ID: "external", + Node: "external", + Address: "web.external.service", + Datacenter: "dc1", + }, + Service: &structs.NodeService{ + Service: "web", + Port: 9090, + }, + }, + }, + }, + }, + }) +} + +func TestConfigSnapshotTerminatingGatewaySubsetsHTTP2(t testing.T) *ConfigSnapshot { + web := structs.NewServiceName("web", nil) + + return TestConfigSnapshotTerminatingGateway(t, false, nil, []UpdateEvent{ + { + CorrelationID: serviceResolverIDPrefix + web.String(), + Result: &structs.ConfigEntryResponse{ + Entry: &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: "web", + Subsets: map[string]structs.ServiceResolverSubset{ + "v1": { + Filter: "Service.Meta.version == 1", + }, + "v2": { + Filter: "Service.Meta.version == 2", + }, + }, + }, + }, + }, + { + CorrelationID: gatewayServicesWatchID, + Result: &structs.IndexedGatewayServices{ + Services: []*structs.GatewayService{ + { + Service: web, + CAFile: "ca.cert.pem", + }, + }, + }, + }, + { + CorrelationID: serviceConfigIDPrefix + web.String(), + Result: &structs.ServiceConfigResponse{ + ProxyConfig: map[string]interface{}{"protocol": "http2"}, + }, + }, + { + CorrelationID: externalServiceIDPrefix + web.String(), + Result: &structs.IndexedCheckServiceNodes{ + Nodes: []structs.CheckServiceNode{ + { + Node: &structs.Node{ + ID: "external", + Node: "external", + Address: "web.external.service", + Datacenter: "dc1", + }, + Service: &structs.NodeService{ + Service: "web", + Port: 9090, + Meta: map[string]string{"version": "1"}, + }, + }, + { + Node: &structs.Node{ + ID: "external2", + Node: "external2", + Address: "web.external2.service", + Datacenter: "dc1", + }, + Service: &structs.NodeService{ + Service: "web", + Port: 9091, + Meta: map[string]string{"version": "2"}, + }, + }, + }, + }, + }, + }) +} + func TestConfigSnapshotTerminatingGatewayHostnameSubsets(t testing.T) *ConfigSnapshot { var ( api = structs.NewServiceName("api", nil) diff --git a/agent/proxycfg/upstreams.go b/agent/proxycfg/upstreams.go index 1f1251c42c..a47510543c 100644 --- a/agent/proxycfg/upstreams.go +++ b/agent/proxycfg/upstreams.go @@ -71,7 +71,8 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv case structs.ServiceKindConnectProxy: explicit := snap.ConnectProxy.UpstreamConfig[uid].HasLocalPortOrSocket() - if _, implicit := snap.ConnectProxy.IntentionUpstreams[uid]; !implicit && !explicit { + implicit := snap.ConnectProxy.IsImplicitUpstream(uid) + if !implicit && !explicit { // Discovery chain is not associated with a known explicit or implicit upstream so it is purged/skipped. // The associated watch was likely cancelled. delete(upstreamsSnapshot.DiscoveryChain, uid) @@ -103,19 +104,15 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv resp.Nodes, ) if len(filteredNodes) > 0 { - upstreamsSnapshot.PeerUpstreamEndpoints[uid] = filteredNodes - upstreamsSnapshot.PeerUpstreamEndpointsUseHostnames[uid] = struct{}{} + if set := upstreamsSnapshot.PeerUpstreamEndpoints.Set(uid, filteredNodes); set { + upstreamsSnapshot.PeerUpstreamEndpointsUseHostnames[uid] = struct{}{} + } } else { - upstreamsSnapshot.PeerUpstreamEndpoints[uid] = resp.Nodes - delete(upstreamsSnapshot.PeerUpstreamEndpointsUseHostnames, uid) + if set := upstreamsSnapshot.PeerUpstreamEndpoints.Set(uid, resp.Nodes); set { + delete(upstreamsSnapshot.PeerUpstreamEndpointsUseHostnames, uid) + } } - if s.kind != structs.ServiceKindConnectProxy || s.proxyCfg.Mode != structs.ProxyModeTransparent { - return nil - } - - s.logger.Warn("skipping transparent proxy update for peered upstream") - case strings.HasPrefix(u.CorrelationID, "upstream-target:"): resp, ok := u.Result.(*structs.IndexedCheckServiceNodes) if !ok { @@ -157,6 +154,10 @@ func (s *handlerUpstreams) handleUpdateUpstreams(ctx context.Context, u UpdateEv // Make sure to use an external address when crossing partition or DC boundaries. isRemote := !snap.Locality.Matches(node.Node.Datacenter, node.Node.PartitionOrDefault()) + // If node is peered it must be remote + if node.Node.PeerOrEmpty() != "" { + isRemote = true + } csnIdx, addr, _ := node.BestAddress(isRemote) existing := upstreamsSnapshot.PassthroughIndices[addr] diff --git a/agent/rpc/peering/service.go b/agent/rpc/peering/service.go index 3720ec135d..94b7d73a30 100644 --- a/agent/rpc/peering/service.go +++ b/agent/rpc/peering/service.go @@ -4,25 +4,21 @@ import ( "context" "errors" "fmt" - "io" "strings" "time" "github.com/armon/go-metrics" - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/proto" "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-memdb" - "google.golang.org/genproto/googleapis/rpc/code" "google.golang.org/grpc" "google.golang.org/grpc/codes" grpcstatus "google.golang.org/grpc/status" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" "github.com/hashicorp/consul/agent/dns" + "github.com/hashicorp/consul/agent/grpc-external/services/peerstream" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/proto/pbpeering" @@ -46,30 +42,45 @@ func (e *errPeeringInvalidServerAddress) Error() string { return fmt.Sprintf("%s is not a valid peering server address", e.addr) } +// Server implements pbpeering.PeeringService to provide RPC operations for +// managing peering relationships. +type Server struct { + Config +} + type Config struct { + Backend Backend + Tracker *peerstream.Tracker + Logger hclog.Logger + ForwardRPC func(structs.RPCInfo, func(*grpc.ClientConn) error) (bool, error) Datacenter string ConnectEnabled bool } -// Service implements pbpeering.PeeringService to provide RPC operations for -// managing peering relationships. -type Service struct { - Backend Backend - logger hclog.Logger - config Config - streams *streamTracker -} - -func NewService(logger hclog.Logger, cfg Config, backend Backend) *Service { - return &Service{ - Backend: backend, - logger: logger, - config: cfg, - streams: newStreamTracker(), +func NewServer(cfg Config) *Server { + requireNotNil(cfg.Backend, "Backend") + requireNotNil(cfg.Tracker, "Tracker") + requireNotNil(cfg.Logger, "Logger") + requireNotNil(cfg.ForwardRPC, "ForwardRPC") + if cfg.Datacenter == "" { + panic("Datacenter is required") + } + return &Server{ + Config: cfg, } } -var _ pbpeering.PeeringServiceServer = (*Service)(nil) +func requireNotNil(v interface{}, name string) { + if v == nil { + panic(name + " is required") + } +} + +var _ pbpeering.PeeringServiceServer = (*Server)(nil) + +func (s *Server) Register(grpcServer *grpc.Server) { + pbpeering.RegisterPeeringServiceServer(grpcServer, s) +} // Backend defines the core integrations the Peering endpoint depends on. A // functional implementation will integrate with various subcomponents of Consul @@ -77,9 +88,6 @@ var _ pbpeering.PeeringServiceServer = (*Service)(nil) // providing access to CA data and the RPC system for forwarding requests to // other servers. type Backend interface { - // Forward should forward the request to the leader when necessary. - Forward(info structs.RPCInfo, f func(*grpc.ClientConn) error) (handled bool, err error) - // GetAgentCACertificates returns the CA certificate to be returned in the peering token data GetAgentCACertificates() ([]string, error) @@ -105,22 +113,19 @@ type Backend interface { // IsLeader indicates whether the consul server is in a leader state or not. IsLeader() bool + // SetLeaderAddress is called on a raft.LeaderObservation in a go routine + // in the consul server; see trackLeaderChanges() + SetLeaderAddress(string) + + // GetLeaderAddress provides the best hint for the current address of the + // leader. There is no guarantee that this is the actual address of the + // leader. + GetLeaderAddress() string + + CheckPeeringUUID(id string) (bool, error) + PeeringWrite(req *pbpeering.PeeringWriteRequest) error + Store() Store - Apply() Apply - LeaderAddress() LeaderAddress -} - -// LeaderAddress provides a way for the consul server to update the peering service about -// the server's leadership status. -// Server addresses should look like: ip:port -type LeaderAddress interface { - // Set is called on a raft.LeaderObservation in a go routine in the consul server; - // see trackLeaderChanges() - Set(leaderAddr string) - - // Get provides the best hint for the current address of the leader. - // There is no guarantee that this is the actual address of the leader. - Get() string } // Store provides a read-only interface for querying Peering data. @@ -130,29 +135,13 @@ type Store interface { PeeringList(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.Peering, error) PeeringTrustBundleRead(ws memdb.WatchSet, q state.Query) (uint64, *pbpeering.PeeringTrustBundle, error) PeeringTrustBundleList(ws memdb.WatchSet, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.PeeringTrustBundle, error) - ExportedServicesForPeer(ws memdb.WatchSet, peerID, dc string) (uint64, *structs.ExportedServiceList, error) - ServiceDump(ws memdb.WatchSet, kind structs.ServiceKind, useKind bool, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) - CheckServiceNodes(ws memdb.WatchSet, serviceName string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, structs.CheckServiceNodes, error) - NodeServices(ws memdb.WatchSet, nodeNameOrID string, entMeta *acl.EnterpriseMeta, peerName string) (uint64, *structs.NodeServices, error) - CAConfig(ws memdb.WatchSet) (uint64, *structs.CAConfiguration, error) TrustBundleListByService(ws memdb.WatchSet, service, dc string, entMeta acl.EnterpriseMeta) (uint64, []*pbpeering.PeeringTrustBundle, error) - AbandonCh() <-chan struct{} -} - -// Apply provides a write-only interface for persisting Peering data. -type Apply interface { - CheckPeeringUUID(id string) (bool, error) - PeeringWrite(req *pbpeering.PeeringWriteRequest) error - PeeringTerminateByID(req *pbpeering.PeeringTerminateByIDRequest) error - PeeringTrustBundleWrite(req *pbpeering.PeeringTrustBundleWriteRequest) error - CatalogRegister(req *structs.RegisterRequest) error - CatalogDeregister(req *structs.DeregisterRequest) error } // GenerateToken implements the PeeringService RPC method to generate a // peering token which is the initial step in establishing a peering relationship // with other Consul clusters. -func (s *Service) GenerateToken( +func (s *Server) GenerateToken( ctx context.Context, req *pbpeering.GenerateTokenRequest, ) (*pbpeering.GenerateTokenResponse, error) { @@ -172,7 +161,7 @@ func (s *Service) GenerateToken( // TODO(peering): add tracing resp := &pbpeering.GenerateTokenResponse{} - handled, err := s.Backend.Forward(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { var err error resp, err = pbpeering.NewPeeringServiceClient(conn).GenerateToken(ctx, req) return err @@ -207,7 +196,7 @@ RETRY_ONCE: Meta: req.Meta, }, } - if err := s.Backend.Apply().PeeringWrite(&writeReq); err != nil { + if err := s.Backend.PeeringWrite(&writeReq); err != nil { // There's a possible race where two servers call Generate Token at the // same time with the same peer name for the first time. They both // generate an ID and try to insert and only one wins. This detects the @@ -251,7 +240,7 @@ RETRY_ONCE: // Establish implements the PeeringService RPC method to finalize peering // registration. Given a valid token output from a peer's GenerateToken endpoint, // a peering is registered. -func (s *Service) Establish( +func (s *Server) Establish( ctx context.Context, req *pbpeering.EstablishRequest, ) (*pbpeering.EstablishResponse, error) { @@ -272,7 +261,7 @@ func (s *Service) Establish( } resp := &pbpeering.EstablishResponse{} - handled, err := s.Backend.Forward(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { var err error resp, err = pbpeering.NewPeeringServiceClient(conn).Establish(ctx, req) return err @@ -312,20 +301,20 @@ func (s *Service) Establish( State: pbpeering.PeeringState_ESTABLISHING, }, } - if err = s.Backend.Apply().PeeringWrite(writeReq); err != nil { + if err = s.Backend.PeeringWrite(writeReq); err != nil { return nil, fmt.Errorf("failed to write peering: %w", err) } // resp.Status == 0 return resp, nil } -func (s *Service) PeeringRead(ctx context.Context, req *pbpeering.PeeringReadRequest) (*pbpeering.PeeringReadResponse, error) { +func (s *Server) PeeringRead(ctx context.Context, req *pbpeering.PeeringReadRequest) (*pbpeering.PeeringReadResponse, error) { if err := s.Backend.EnterpriseCheckPartitions(req.Partition); err != nil { return nil, grpcstatus.Error(codes.InvalidArgument, err.Error()) } var resp *pbpeering.PeeringReadResponse - handled, err := s.Backend.Forward(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { var err error resp, err = pbpeering.NewPeeringServiceClient(conn).PeeringRead(ctx, req) return err @@ -352,13 +341,13 @@ func (s *Service) PeeringRead(ctx context.Context, req *pbpeering.PeeringReadReq return &pbpeering.PeeringReadResponse{Peering: cp}, nil } -func (s *Service) PeeringList(ctx context.Context, req *pbpeering.PeeringListRequest) (*pbpeering.PeeringListResponse, error) { +func (s *Server) PeeringList(ctx context.Context, req *pbpeering.PeeringListRequest) (*pbpeering.PeeringListResponse, error) { if err := s.Backend.EnterpriseCheckPartitions(req.Partition); err != nil { return nil, grpcstatus.Error(codes.InvalidArgument, err.Error()) } var resp *pbpeering.PeeringListResponse - handled, err := s.Backend.Forward(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { var err error resp, err = pbpeering.NewPeeringServiceClient(conn).PeeringList(ctx, req) return err @@ -388,8 +377,8 @@ func (s *Service) PeeringList(ctx context.Context, req *pbpeering.PeeringListReq // TODO(peering): Maybe get rid of this when actually monitoring the stream health // reconciledStreamStateHint peaks into the streamTracker and determines whether a peering should be marked // as PeeringState.Active or not -func (s *Service) reconciledStreamStateHint(pID string, pState pbpeering.PeeringState) pbpeering.PeeringState { - streamState, found := s.streams.streamStatus(pID) +func (s *Server) reconciledStreamStateHint(pID string, pState pbpeering.PeeringState) pbpeering.PeeringState { + streamState, found := s.Tracker.StreamStatus(pID) if found && streamState.Connected { return pbpeering.PeeringState_ACTIVE @@ -401,13 +390,13 @@ func (s *Service) reconciledStreamStateHint(pID string, pState pbpeering.Peering // TODO(peering): As of writing, this method is only used in tests to set up Peerings in the state store. // Consider removing if we can find another way to populate state store in peering_endpoint_test.go -func (s *Service) PeeringWrite(ctx context.Context, req *pbpeering.PeeringWriteRequest) (*pbpeering.PeeringWriteResponse, error) { +func (s *Server) PeeringWrite(ctx context.Context, req *pbpeering.PeeringWriteRequest) (*pbpeering.PeeringWriteResponse, error) { if err := s.Backend.EnterpriseCheckPartitions(req.Peering.Partition); err != nil { return nil, grpcstatus.Error(codes.InvalidArgument, err.Error()) } var resp *pbpeering.PeeringWriteResponse - handled, err := s.Backend.Forward(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { var err error resp, err = pbpeering.NewPeeringServiceClient(conn).PeeringWrite(ctx, req) return err @@ -430,20 +419,20 @@ func (s *Service) PeeringWrite(ctx context.Context, req *pbpeering.PeeringWriteR req.Peering.ID = id // TODO(peering): handle blocking queries - err = s.Backend.Apply().PeeringWrite(req) + err = s.Backend.PeeringWrite(req) if err != nil { return nil, err } return &pbpeering.PeeringWriteResponse{}, nil } -func (s *Service) PeeringDelete(ctx context.Context, req *pbpeering.PeeringDeleteRequest) (*pbpeering.PeeringDeleteResponse, error) { +func (s *Server) PeeringDelete(ctx context.Context, req *pbpeering.PeeringDeleteRequest) (*pbpeering.PeeringDeleteResponse, error) { if err := s.Backend.EnterpriseCheckPartitions(req.Partition); err != nil { return nil, grpcstatus.Error(codes.InvalidArgument, err.Error()) } var resp *pbpeering.PeeringDeleteResponse - handled, err := s.Backend.Forward(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { var err error resp, err = pbpeering.NewPeeringServiceClient(conn).PeeringDelete(ctx, req) return err @@ -486,20 +475,20 @@ func (s *Service) PeeringDelete(ctx context.Context, req *pbpeering.PeeringDelet DeletedAt: structs.TimeToProto(time.Now().UTC()), }, } - err = s.Backend.Apply().PeeringWrite(writeReq) + err = s.Backend.PeeringWrite(writeReq) if err != nil { return nil, err } return &pbpeering.PeeringDeleteResponse{}, nil } -func (s *Service) TrustBundleRead(ctx context.Context, req *pbpeering.TrustBundleReadRequest) (*pbpeering.TrustBundleReadResponse, error) { +func (s *Server) TrustBundleRead(ctx context.Context, req *pbpeering.TrustBundleReadRequest) (*pbpeering.TrustBundleReadResponse, error) { if err := s.Backend.EnterpriseCheckPartitions(req.Partition); err != nil { return nil, grpcstatus.Error(codes.InvalidArgument, err.Error()) } var resp *pbpeering.TrustBundleReadResponse - handled, err := s.Backend.Forward(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { var err error resp, err = pbpeering.NewPeeringServiceClient(conn).TrustBundleRead(ctx, req) return err @@ -528,7 +517,7 @@ func (s *Service) TrustBundleRead(ctx context.Context, req *pbpeering.TrustBundl } // TODO(peering): rename rpc & request/response to drop the "service" part -func (s *Service) TrustBundleListByService(ctx context.Context, req *pbpeering.TrustBundleListByServiceRequest) (*pbpeering.TrustBundleListByServiceResponse, error) { +func (s *Server) TrustBundleListByService(ctx context.Context, req *pbpeering.TrustBundleListByServiceRequest) (*pbpeering.TrustBundleListByServiceResponse, error) { if err := s.Backend.EnterpriseCheckPartitions(req.Partition); err != nil { return nil, grpcstatus.Error(codes.InvalidArgument, err.Error()) } @@ -537,7 +526,7 @@ func (s *Service) TrustBundleListByService(ctx context.Context, req *pbpeering.T } var resp *pbpeering.TrustBundleListByServiceResponse - handled, err := s.Backend.Forward(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { var err error resp, err = pbpeering.NewPeeringServiceClient(conn).TrustBundleListByService(ctx, req) return err @@ -560,7 +549,7 @@ func (s *Service) TrustBundleListByService(ctx context.Context, req *pbpeering.T switch { case req.ServiceName != "": - idx, bundles, err = s.Backend.Store().TrustBundleListByService(nil, req.ServiceName, s.config.Datacenter, entMeta) + idx, bundles, err = s.Backend.Store().TrustBundleListByService(nil, req.ServiceName, s.Datacenter, entMeta) case req.Kind == string(structs.ServiceKindMeshGateway): idx, bundles, err = s.Backend.Store().PeeringTrustBundleList(nil, entMeta) case req.Kind != "": @@ -575,332 +564,7 @@ func (s *Service) TrustBundleListByService(ctx context.Context, req *pbpeering.T return &pbpeering.TrustBundleListByServiceResponse{Index: idx, Bundles: bundles}, nil } -type BidirectionalStream interface { - Send(*pbpeering.ReplicationMessage) error - Recv() (*pbpeering.ReplicationMessage, error) - Context() context.Context -} - -// StreamResources handles incoming streaming connections. -func (s *Service) StreamResources(stream pbpeering.PeeringService_StreamResourcesServer) error { - if !s.Backend.IsLeader() { - // we are not the leader so we will hang up on the dialer - - s.logger.Error("cannot establish a peering stream on a follower node") - - st, err := grpcstatus.New(codes.FailedPrecondition, - "cannot establish a peering stream on a follower node").WithDetails( - &pbpeering.LeaderAddress{Address: s.Backend.LeaderAddress().Get()}) - if err != nil { - s.logger.Error(fmt.Sprintf("failed to marshal the leader address in response; err: %v", err)) - return grpcstatus.Error(codes.FailedPrecondition, "cannot establish a peering stream on a follower node") - } else { - return st.Err() - } - } - - // Initial message on a new stream must be a new subscription request. - first, err := stream.Recv() - if err != nil { - s.logger.Error("failed to establish stream", "error", err) - return err - } - - // TODO(peering) Make request contain a list of resources, so that roots and services can be - // subscribed to with a single request. See: - // https://github.com/envoyproxy/data-plane-api/blob/main/envoy/service/discovery/v3/discovery.proto#L46 - req := first.GetRequest() - if req == nil { - return grpcstatus.Error(codes.InvalidArgument, "first message when initiating a peering must be a subscription request") - } - s.logger.Trace("received initial replication request from peer") - logTraceRecv(s.logger, req) - - if req.PeerID == "" { - return grpcstatus.Error(codes.InvalidArgument, "initial subscription request must specify a PeerID") - } - if req.Nonce != "" { - return grpcstatus.Error(codes.InvalidArgument, "initial subscription request must not contain a nonce") - } - if !pbpeering.KnownTypeURL(req.ResourceURL) { - return grpcstatus.Error(codes.InvalidArgument, fmt.Sprintf("subscription request to unknown resource URL: %s", req.ResourceURL)) - } - - _, p, err := s.Backend.Store().PeeringReadByID(nil, req.PeerID) - if err != nil { - s.logger.Error("failed to look up peer", "peer_id", req.PeerID, "error", err) - return grpcstatus.Error(codes.Internal, "failed to find PeerID: "+req.PeerID) - } - if p == nil { - return grpcstatus.Error(codes.InvalidArgument, "initial subscription for unknown PeerID: "+req.PeerID) - } - - // TODO(peering): If the peering is marked as deleted, send a Terminated message and return - // TODO(peering): Store subscription request so that an event publisher can separately handle pushing messages for it - s.logger.Info("accepted initial replication request from peer", "peer_id", p.ID) - - streamReq := HandleStreamRequest{ - LocalID: p.ID, - RemoteID: p.PeerID, - PeerName: p.Name, - Partition: p.Partition, - Stream: stream, - } - err = s.HandleStream(streamReq) - // A nil error indicates that the peering was deleted and the stream needs to be gracefully shutdown. - if err == nil { - s.DrainStream(streamReq) - return nil - } - - s.logger.Error("error handling stream", "peer_name", p.Name, "peer_id", req.PeerID, "error", err) - return err -} - -type HandleStreamRequest struct { - // LocalID is the UUID for the peering in the local Consul datacenter. - LocalID string - - // RemoteID is the UUID for the peering from the perspective of the peer. - RemoteID string - - // PeerName is the name of the peering. - PeerName string - - // Partition is the local partition associated with the peer. - Partition string - - // Stream is the open stream to the peer cluster. - Stream BidirectionalStream -} - -// DrainStream attempts to gracefully drain the stream when the connection is going to be torn down. -// Tearing down the connection too quickly can lead our peer receiving a context cancellation error before the stream termination message. -// Handling the termination message is important to set the expectation that the peering will not be reestablished unless recreated. -func (s *Service) DrainStream(req HandleStreamRequest) { - for { - // Ensure that we read until an error, or the peer has nothing more to send. - if _, err := req.Stream.Recv(); err != nil { - if err != io.EOF { - s.logger.Warn("failed to tear down stream gracefully: peer may not have received termination message", - "peer_name", req.PeerName, "peer_id", req.LocalID, "error", err) - } - break - } - // Since the peering is being torn down we discard all replication messages without an error. - // We want to avoid importing new data at this point. - } -} - -// The localID provided is the locally-generated identifier for the peering. -// The remoteID is an identifier that the remote peer recognizes for the peering. -func (s *Service) HandleStream(req HandleStreamRequest) error { - logger := s.logger.Named("stream").With("peer_name", req.PeerName, "peer_id", req.LocalID) - logger.Trace("handling stream for peer") - - status, err := s.streams.connected(req.LocalID) - if err != nil { - return fmt.Errorf("failed to register stream: %v", err) - } - - // TODO(peering) Also need to clear subscriptions associated with the peer - defer s.streams.disconnected(req.LocalID) - - var trustDomain string - if s.config.ConnectEnabled { - // Read the TrustDomain up front - we do not allow users to change the ClusterID - // so reading it once at the beginning of the stream is sufficient. - trustDomain, err = getTrustDomain(s.Backend.Store(), logger) - if err != nil { - return err - } - } - - mgr := newSubscriptionManager( - req.Stream.Context(), - logger, - s.config, - trustDomain, - s.Backend, - ) - subCh := mgr.subscribe(req.Stream.Context(), req.LocalID, req.PeerName, req.Partition) - - sub := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - ResourceURL: pbpeering.TypeURLService, - PeerID: req.RemoteID, - }, - }, - } - logTraceSend(logger, sub) - - if err := req.Stream.Send(sub); err != nil { - if err == io.EOF { - logger.Info("stream ended by peer") - status.trackReceiveError(err.Error()) - return nil - } - // TODO(peering) Test error handling in calls to Send/Recv - status.trackSendError(err.Error()) - return fmt.Errorf("failed to send to stream: %v", err) - } - - // TODO(peering): Should this be buffered? - recvChan := make(chan *pbpeering.ReplicationMessage) - go func() { - defer close(recvChan) - for { - msg, err := req.Stream.Recv() - if err == nil { - logTraceRecv(logger, msg) - recvChan <- msg - continue - } - - if err == io.EOF { - logger.Info("stream ended by peer") - status.trackReceiveError(err.Error()) - return - } - logger.Error("failed to receive from stream", "error", err) - status.trackReceiveError(err.Error()) - return - } - }() - - for { - select { - // When the doneCh is closed that means that the peering was deleted locally. - case <-status.doneCh: - logger.Info("ending stream") - - term := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Terminated_{ - Terminated: &pbpeering.ReplicationMessage_Terminated{}, - }, - } - logTraceSend(logger, term) - - if err := req.Stream.Send(term); err != nil { - status.trackSendError(err.Error()) - return fmt.Errorf("failed to send to stream: %v", err) - } - - logger.Trace("deleting stream status") - s.streams.deleteStatus(req.LocalID) - - return nil - - case msg, open := <-recvChan: - if !open { - logger.Trace("no longer receiving data on the stream") - return nil - } - - if !s.Backend.IsLeader() { - // we are not the leader anymore so we will hang up on the dialer - logger.Error("node is not a leader anymore; cannot continue streaming") - - st, err := grpcstatus.New(codes.FailedPrecondition, - "node is not a leader anymore; cannot continue streaming").WithDetails( - &pbpeering.LeaderAddress{Address: s.Backend.LeaderAddress().Get()}) - if err != nil { - s.logger.Error(fmt.Sprintf("failed to marshal the leader address in response; err: %v", err)) - return grpcstatus.Error(codes.FailedPrecondition, "node is not a leader anymore; cannot continue streaming") - } else { - return st.Err() - } - } - - if req := msg.GetRequest(); req != nil { - switch { - case req.Nonce == "": - // TODO(peering): This can happen on a client peer since they don't try to receive subscriptions before entering HandleStream. - // Should change that behavior or only allow it that one time. - - case req.Error != nil && (req.Error.Code != int32(code.Code_OK) || req.Error.Message != ""): - logger.Warn("client peer was unable to apply resource", "code", req.Error.Code, "error", req.Error.Message) - status.trackNack(fmt.Sprintf("client peer was unable to apply resource: %s", req.Error.Message)) - - default: - status.trackAck() - } - - continue - } - - if resp := msg.GetResponse(); resp != nil { - // TODO(peering): Ensure there's a nonce - reply, err := s.processResponse(req.PeerName, req.Partition, resp) - if err != nil { - logger.Error("failed to persist resource", "resourceURL", resp.ResourceURL, "resourceID", resp.ResourceID) - status.trackReceiveError(err.Error()) - } else { - status.trackReceiveSuccess() - } - - logTraceSend(logger, reply) - if err := req.Stream.Send(reply); err != nil { - status.trackSendError(err.Error()) - return fmt.Errorf("failed to send to stream: %v", err) - } - - continue - } - - if term := msg.GetTerminated(); term != nil { - logger.Info("peering was deleted by our peer: marking peering as terminated and cleaning up imported resources") - - // Once marked as terminated, a separate deferred deletion routine will clean up imported resources. - if err := s.Backend.Apply().PeeringTerminateByID(&pbpeering.PeeringTerminateByIDRequest{ID: req.LocalID}); err != nil { - logger.Error("failed to mark peering as terminated: %w", err) - } - return nil - } - - case update := <-subCh: - var resp *pbpeering.ReplicationMessage - switch { - case strings.HasPrefix(update.CorrelationID, subExportedService): - resp = makeServiceResponse(logger, update) - - case strings.HasPrefix(update.CorrelationID, subMeshGateway): - // TODO(Peering): figure out how to sync this separately - - case update.CorrelationID == subCARoot: - resp = makeCARootsResponse(logger, update) - - default: - logger.Warn("unrecognized update type from subscription manager: " + update.CorrelationID) - continue - } - if resp == nil { - continue - } - logTraceSend(logger, resp) - if err := req.Stream.Send(resp); err != nil { - status.trackSendError(err.Error()) - return fmt.Errorf("failed to push data for %q: %w", update.CorrelationID, err) - } - } - } -} - -func getTrustDomain(store Store, logger hclog.Logger) (string, error) { - _, cfg, err := store.CAConfig(nil) - switch { - case err != nil: - logger.Error("failed to read Connect CA Config", "error", err) - return "", grpcstatus.Error(codes.Internal, "failed to read Connect CA Config") - case cfg == nil: - logger.Warn("cannot begin stream because Connect CA is not yet initialized") - return "", grpcstatus.Error(codes.FailedPrecondition, "Connect CA is not yet initialized") - } - return connect.SpiffeIDSigningForCluster(cfg.ClusterID).Host(), nil -} - -func (s *Service) getExistingOrCreateNewPeerID(peerName, partition string) (string, error) { +func (s *Server) getExistingOrCreateNewPeerID(peerName, partition string) (string, error) { q := state.Query{ Value: strings.ToLower(peerName), EnterpriseMeta: *structs.NodeEnterpriseMetaInPartition(partition), @@ -913,51 +577,13 @@ func (s *Service) getExistingOrCreateNewPeerID(peerName, partition string) (stri return peering.ID, nil } - id, err := lib.GenerateUUID(s.Backend.Apply().CheckPeeringUUID) + id, err := lib.GenerateUUID(s.Backend.CheckPeeringUUID) if err != nil { return "", err } return id, nil } -func (s *Service) StreamStatus(peer string) (resp StreamStatus, found bool) { - return s.streams.streamStatus(peer) -} - -// ConnectedStreams returns a map of connected stream IDs to the corresponding channel for tearing them down. -func (s *Service) ConnectedStreams() map[string]chan struct{} { - return s.streams.connectedStreams() -} - -func logTraceRecv(logger hclog.Logger, pb proto.Message) { - logTraceProto(logger, pb, true) -} - -func logTraceSend(logger hclog.Logger, pb proto.Message) { - logTraceProto(logger, pb, false) -} - -func logTraceProto(logger hclog.Logger, pb proto.Message, received bool) { - if !logger.IsTrace() { - return - } - - dir := "sent" - if received { - dir = "received" - } - - m := jsonpb.Marshaler{ - Indent: " ", - } - out, err := m.MarshalToString(pb) - if err != nil { - out = "" - } - - logger.Trace("replication message", "direction", dir, "protobuf", out) -} - func copyPeeringWithNewState(p *pbpeering.Peering, state pbpeering.PeeringState) *pbpeering.Peering { return &pbpeering.Peering{ ID: p.ID, diff --git a/agent/rpc/peering/service_test.go b/agent/rpc/peering/service_test.go index ca9737f656..6a8f32915b 100644 --- a/agent/rpc/peering/service_test.go +++ b/agent/rpc/peering/service_test.go @@ -14,26 +14,22 @@ import ( "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-uuid" "github.com/stretchr/testify/require" - "golang.org/x/sync/errgroup" gogrpc "google.golang.org/grpc" - "google.golang.org/protobuf/types/known/anypb" "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" - grpc "github.com/hashicorp/consul/agent/grpc/private" - "github.com/hashicorp/consul/agent/grpc/private/resolver" + grpc "github.com/hashicorp/consul/agent/grpc-internal" + "github.com/hashicorp/consul/agent/grpc-internal/resolver" "github.com/hashicorp/consul/agent/pool" "github.com/hashicorp/consul/agent/router" "github.com/hashicorp/consul/agent/rpc/middleware" "github.com/hashicorp/consul/agent/rpc/peering" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/token" - "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/proto/pbpeering" - "github.com/hashicorp/consul/proto/pbservice" "github.com/hashicorp/consul/proto/prototest" "github.com/hashicorp/consul/sdk/freeport" "github.com/hashicorp/consul/sdk/testutil" @@ -70,8 +66,6 @@ func TestPeeringService_GenerateToken(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) t.Cleanup(cancel) - expectedAddr := s.Server.Listener.Addr().String() - // TODO(peering): for more failure cases, consider using a table test // check meta tags reqE := pbpeering.GenerateTokenRequest{PeerName: "peerB", Datacenter: "dc1", Meta: generateTooManyMetaKeys()} @@ -90,7 +84,7 @@ func TestPeeringService_GenerateToken(t *testing.T) { require.NoError(t, json.Unmarshal(tokenJSON, token)) require.Equal(t, "server.dc1.consul", token.ServerName) require.Len(t, token.ServerAddresses, 1) - require.Equal(t, expectedAddr, token.ServerAddresses[0]) + require.Equal(t, s.PublicGRPCAddr, token.ServerAddresses[0]) require.Equal(t, []string{ca}, token.CA) require.NotEmpty(t, token.PeerID) @@ -501,387 +495,6 @@ func TestPeeringService_TrustBundleListByService(t *testing.T) { require.Equal(t, []string{"foo-root-1"}, resp.Bundles[1].RootPEMs) } -func Test_StreamHandler_UpsertServices(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - type testCase struct { - name string - msg *pbpeering.ReplicationMessage_Response - input structs.CheckServiceNodes - expect structs.CheckServiceNodes - } - - s := newTestServer(t, nil) - testrpc.WaitForLeader(t, s.Server.RPC, "dc1") - testrpc.WaitForActiveCARoot(t, s.Server.RPC, "dc1", nil) - - srv := peering.NewService( - testutil.Logger(t), - peering.Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, - consul.NewPeeringBackend(s.Server, nil), - ) - - require.NoError(t, s.Server.FSM().State().PeeringWrite(0, &pbpeering.Peering{ - ID: testUUID(t), - Name: "my-peer", - })) - - _, p, err := s.Server.FSM().State().PeeringRead(nil, state.Query{Value: "my-peer"}) - require.NoError(t, err) - - client := peering.NewMockClient(context.Background()) - - errCh := make(chan error, 1) - client.ErrCh = errCh - - go func() { - // Pass errors from server handler into ErrCh so that they can be seen by the client on Recv(). - // This matches gRPC's behavior when an error is returned by a server. - err := srv.StreamResources(client.ReplicationStream) - if err != nil { - errCh <- err - } - }() - - sub := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Request_{ - Request: &pbpeering.ReplicationMessage_Request{ - PeerID: p.ID, - ResourceURL: pbpeering.TypeURLService, - }, - }, - } - require.NoError(t, client.Send(sub)) - - // Receive subscription request from peer for our services - _, err = client.Recv() - require.NoError(t, err) - - // Receive first roots replication message - receiveRoots, err := client.Recv() - require.NoError(t, err) - require.NotNil(t, receiveRoots.GetResponse()) - require.Equal(t, pbpeering.TypeURLRoots, receiveRoots.GetResponse().ResourceURL) - - remoteEntMeta := structs.DefaultEnterpriseMetaInPartition("remote-partition") - localEntMeta := acl.DefaultEnterpriseMeta() - localPeerName := "my-peer" - - // Scrub data we don't need for the assertions below. - scrubCheckServiceNodes := func(instances structs.CheckServiceNodes) { - for _, csn := range instances { - csn.Node.RaftIndex = structs.RaftIndex{} - - csn.Service.TaggedAddresses = nil - csn.Service.Weights = nil - csn.Service.RaftIndex = structs.RaftIndex{} - csn.Service.Proxy = structs.ConnectProxyConfig{} - - for _, c := range csn.Checks { - c.RaftIndex = structs.RaftIndex{} - c.Definition = structs.HealthCheckDefinition{} - } - } - } - - run := func(t *testing.T, tc testCase) { - pbCSN := &pbservice.IndexedCheckServiceNodes{} - for _, csn := range tc.input { - pbCSN.Nodes = append(pbCSN.Nodes, pbservice.NewCheckServiceNodeFromStructs(&csn)) - } - - any, err := anypb.New(pbCSN) - require.NoError(t, err) - tc.msg.Resource = any - - resp := &pbpeering.ReplicationMessage{ - Payload: &pbpeering.ReplicationMessage_Response_{ - Response: tc.msg, - }, - } - require.NoError(t, client.Send(resp)) - - msg, err := client.RecvWithTimeout(1 * time.Second) - require.NoError(t, err) - - req := msg.GetRequest() - require.NotNil(t, req) - require.Equal(t, tc.msg.Nonce, req.Nonce) - require.Nil(t, req.Error) - - _, got, err := s.Server.FSM().State().CombinedCheckServiceNodes(nil, structs.NewServiceName("api", nil), localPeerName) - require.NoError(t, err) - - scrubCheckServiceNodes(got) - require.Equal(t, tc.expect, got) - } - - // NOTE: These test cases do not run against independent state stores, they show sequential updates for a given service. - // Every new upsert must replace the data from the previous case. - tt := []testCase{ - { - name: "upsert an instance on a node", - msg: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, - ResourceID: "api", - Nonce: "1", - Operation: pbpeering.ReplicationMessage_Response_UPSERT, - }, - input: structs.CheckServiceNodes{ - { - Node: &structs.Node{ - ID: "112e2243-ab62-4e8a-9317-63306972183c", - Node: "node-1", - Address: "10.0.0.1", - Datacenter: "dc1", - Partition: remoteEntMeta.PartitionOrEmpty(), - }, - Service: &structs.NodeService{ - Kind: "", - ID: "api-1", - Service: "api", - Port: 8080, - EnterpriseMeta: *remoteEntMeta, - }, - Checks: []*structs.HealthCheck{ - { - CheckID: "node-1-check", - Node: "node-1", - Status: api.HealthPassing, - EnterpriseMeta: *remoteEntMeta, - }, - { - CheckID: "api-1-check", - ServiceID: "api-1", - ServiceName: "api", - Node: "node-1", - Status: api.HealthCritical, - EnterpriseMeta: *remoteEntMeta, - }, - }, - }, - }, - expect: structs.CheckServiceNodes{ - { - Node: &structs.Node{ - ID: "112e2243-ab62-4e8a-9317-63306972183c", - Node: "node-1", - Address: "10.0.0.1", - Datacenter: "dc1", - Partition: localEntMeta.PartitionOrEmpty(), - PeerName: localPeerName, - }, - Service: &structs.NodeService{ - Kind: "", - ID: "api-1", - Service: "api", - Port: 8080, - EnterpriseMeta: *localEntMeta, - PeerName: localPeerName, - }, - Checks: []*structs.HealthCheck{ - { - CheckID: "node-1-check", - Node: "node-1", - Status: api.HealthPassing, - EnterpriseMeta: *localEntMeta, - PeerName: localPeerName, - }, - { - CheckID: "api-1-check", - ServiceID: "api-1", - ServiceName: "api", - Node: "node-1", - Status: api.HealthCritical, - EnterpriseMeta: *localEntMeta, - PeerName: localPeerName, - }, - }, - }, - }, - }, - { - name: "upsert two instances on the same node", - msg: &pbpeering.ReplicationMessage_Response{ - ResourceURL: pbpeering.TypeURLService, - ResourceID: "api", - Nonce: "2", - Operation: pbpeering.ReplicationMessage_Response_UPSERT, - }, - input: structs.CheckServiceNodes{ - { - Node: &structs.Node{ - ID: "112e2243-ab62-4e8a-9317-63306972183c", - Node: "node-1", - Address: "10.0.0.1", - Datacenter: "dc1", - Partition: remoteEntMeta.PartitionOrEmpty(), - }, - Service: &structs.NodeService{ - Kind: "", - ID: "api-1", - Service: "api", - Port: 8080, - EnterpriseMeta: *remoteEntMeta, - }, - Checks: []*structs.HealthCheck{ - { - CheckID: "node-1-check", - Node: "node-1", - Status: api.HealthPassing, - EnterpriseMeta: *remoteEntMeta, - }, - { - CheckID: "api-1-check", - ServiceID: "api-1", - ServiceName: "api", - Node: "node-1", - Status: api.HealthCritical, - EnterpriseMeta: *remoteEntMeta, - }, - }, - }, - { - Node: &structs.Node{ - ID: "112e2243-ab62-4e8a-9317-63306972183c", - Node: "node-1", - Address: "10.0.0.1", - Datacenter: "dc1", - Partition: remoteEntMeta.PartitionOrEmpty(), - }, - Service: &structs.NodeService{ - Kind: "", - ID: "api-2", - Service: "api", - Port: 9090, - EnterpriseMeta: *remoteEntMeta, - }, - Checks: []*structs.HealthCheck{ - { - CheckID: "node-1-check", - Node: "node-1", - Status: api.HealthPassing, - EnterpriseMeta: *remoteEntMeta, - }, - { - CheckID: "api-2-check", - ServiceID: "api-2", - ServiceName: "api", - Node: "node-1", - Status: api.HealthWarning, - EnterpriseMeta: *remoteEntMeta, - }, - }, - }, - }, - expect: structs.CheckServiceNodes{ - { - Node: &structs.Node{ - ID: "112e2243-ab62-4e8a-9317-63306972183c", - Node: "node-1", - Address: "10.0.0.1", - Datacenter: "dc1", - Partition: localEntMeta.PartitionOrEmpty(), - PeerName: localPeerName, - }, - Service: &structs.NodeService{ - Kind: "", - ID: "api-1", - Service: "api", - Port: 8080, - EnterpriseMeta: *localEntMeta, - PeerName: localPeerName, - }, - Checks: []*structs.HealthCheck{ - { - CheckID: "node-1-check", - Node: "node-1", - Status: api.HealthPassing, - EnterpriseMeta: *localEntMeta, - PeerName: localPeerName, - }, - { - CheckID: "api-1-check", - ServiceID: "api-1", - ServiceName: "api", - Node: "node-1", - Status: api.HealthCritical, - EnterpriseMeta: *localEntMeta, - PeerName: localPeerName, - }, - }, - }, - { - Node: &structs.Node{ - ID: "112e2243-ab62-4e8a-9317-63306972183c", - Node: "node-1", - Address: "10.0.0.1", - Datacenter: "dc1", - Partition: localEntMeta.PartitionOrEmpty(), - PeerName: localPeerName, - }, - Service: &structs.NodeService{ - Kind: "", - ID: "api-2", - Service: "api", - Port: 9090, - EnterpriseMeta: *localEntMeta, - PeerName: localPeerName, - }, - Checks: []*structs.HealthCheck{ - { - CheckID: "node-1-check", - Node: "node-1", - Status: api.HealthPassing, - EnterpriseMeta: *localEntMeta, - PeerName: localPeerName, - }, - { - CheckID: "api-2-check", - ServiceID: "api-2", - ServiceName: "api", - Node: "node-1", - Status: api.HealthWarning, - EnterpriseMeta: *localEntMeta, - PeerName: localPeerName, - }, - }, - }, - }, - }, - } - for _, tc := range tt { - testutil.RunStep(t, tc.name, func(t *testing.T) { - run(t, tc) - }) - } - - // call PeeringRead and look at the peering state; the peering state must be active - { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - t.Cleanup(cancel) - - resp, err := srv.PeeringRead(ctx, &pbpeering.PeeringReadRequest{Name: localPeerName}) - require.NoError(t, err) - require.Equal(t, pbpeering.PeeringState_ACTIVE, resp.Peering.State) - } - - // call PeeringList and look at the peering state; the peering state must be active - { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - t.Cleanup(cancel) - - resp, err := srv.PeeringList(ctx, &pbpeering.PeeringListRequest{}) - require.NoError(t, err) - require.Equal(t, pbpeering.PeeringState_ACTIVE, resp.Peerings[0].State) - } -} - // newTestServer is copied from partition/service_test.go, with the addition of certs/cas. // TODO(peering): these are endpoint tests and should live in the agent/consul // package. Instead, these can be written around a mock client (see testing.go) @@ -891,7 +504,7 @@ func newTestServer(t *testing.T, cb func(conf *consul.Config)) testingServer { conf := consul.DefaultConfig() dir := testutil.TempDir(t, "consul") - ports := freeport.GetN(t, 3) // {rpc, serf_lan, serf_wan} + ports := freeport.GetN(t, 4) // {rpc, serf_lan, serf_wan, grpc} conf.Bootstrap = true conf.Datacenter = "dc1" @@ -912,6 +525,8 @@ func newTestServer(t *testing.T, cb func(conf *consul.Config)) testingServer { conf.PrimaryDatacenter = "dc1" conf.ConnectEnabled = true + conf.GRPCPort = ports[3] + nodeID, err := uuid.GenerateUUID() if err != nil { t.Fatal(err) @@ -929,45 +544,31 @@ func newTestServer(t *testing.T, cb func(conf *consul.Config)) testingServer { conf.ACLResolverSettings.Datacenter = conf.Datacenter conf.ACLResolverSettings.EnterpriseMeta = *conf.AgentEnterpriseMeta() + externalGRPCServer := gogrpc.NewServer() + deps := newDefaultDeps(t, conf) - server, err := consul.NewServer(conf, deps, gogrpc.NewServer()) + server, err := consul.NewServer(conf, deps, externalGRPCServer) require.NoError(t, err) t.Cleanup(func() { require.NoError(t, server.Shutdown()) }) + // Normally the gRPC server listener is created at the agent level and + // passed down into the Server creation. + grpcAddr := fmt.Sprintf("127.0.0.1:%d", conf.GRPCPort) + + ln, err := net.Listen("tcp", grpcAddr) + require.NoError(t, err) + go func() { + _ = externalGRPCServer.Serve(ln) + }() + t.Cleanup(externalGRPCServer.Stop) + testrpc.WaitForLeader(t, server.RPC, conf.Datacenter) - backend := consul.NewPeeringBackend(server, deps.GRPCConnPool) - handler := peering.NewService(testutil.Logger(t), peering.Config{ - Datacenter: "dc1", - ConnectEnabled: true, - }, backend) - - grpcServer := gogrpc.NewServer() - pbpeering.RegisterPeeringServiceServer(grpcServer, handler) - - lis, err := net.Listen("tcp", "127.0.0.1:0") - require.NoError(t, err) - t.Cleanup(func() { lis.Close() }) - - g := new(errgroup.Group) - g.Go(func() error { - return grpcServer.Serve(lis) - }) - t.Cleanup(func() { - if grpcServer.Stop(); err != nil { - t.Logf("grpc server shutdown: %v", err) - } - if err := g.Wait(); err != nil { - t.Logf("grpc server error: %v", err) - } - }) - return testingServer{ - Server: server, - Backend: backend, - Addr: lis.Addr(), + Server: server, + PublicGRPCAddr: grpcAddr, } } @@ -976,16 +577,38 @@ func (s testingServer) ClientConn(t *testing.T) *gogrpc.ClientConn { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) t.Cleanup(cancel) - conn, err := gogrpc.DialContext(ctx, s.Addr.String(), gogrpc.WithInsecure()) + rpcAddr := s.Server.Listener.Addr().String() + + conn, err := gogrpc.DialContext(ctx, rpcAddr, + gogrpc.WithContextDialer(newServerDialer(rpcAddr)), + gogrpc.WithInsecure(), + gogrpc.WithBlock()) require.NoError(t, err) t.Cleanup(func() { conn.Close() }) return conn } +func newServerDialer(serverAddr string) func(context.Context, string) (net.Conn, error) { + return func(ctx context.Context, addr string) (net.Conn, error) { + d := net.Dialer{} + conn, err := d.DialContext(ctx, "tcp", serverAddr) + if err != nil { + return nil, err + } + + _, err = conn.Write([]byte{byte(pool.RPCGRPC)}) + if err != nil { + conn.Close() + return nil, err + } + + return conn, nil + } +} + type testingServer struct { - Server *consul.Server - Addr net.Addr - Backend peering.Backend + Server *consul.Server + PublicGRPCAddr string } // TODO(peering): remove duplication between this and agent/consul tests @@ -1056,3 +679,7 @@ func testUUID(t *testing.T) string { require.NoError(t, err) return v } + +func noopForwardRPC(structs.RPCInfo, func(*gogrpc.ClientConn) error) (bool, error) { + return false, nil +} diff --git a/agent/rpc/peering/testing.go b/agent/rpc/peering/testing.go index 312b927206..de64dda7a8 100644 --- a/agent/rpc/peering/testing.go +++ b/agent/rpc/peering/testing.go @@ -1,13 +1,6 @@ package peering import ( - "context" - "io" - "sync" - "time" - - "google.golang.org/grpc/metadata" - "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/pbpeering" ) @@ -73,119 +66,3 @@ func TestPeeringToken(peerID string) structs.PeeringToken { PeerID: peerID, } } - -type MockClient struct { - mu sync.Mutex - - ErrCh chan error - ReplicationStream *MockStream -} - -func (c *MockClient) Send(r *pbpeering.ReplicationMessage) error { - c.ReplicationStream.recvCh <- r - return nil -} - -func (c *MockClient) Recv() (*pbpeering.ReplicationMessage, error) { - select { - case err := <-c.ErrCh: - return nil, err - case r := <-c.ReplicationStream.sendCh: - return r, nil - case <-time.After(10 * time.Millisecond): - return nil, io.EOF - } -} - -func (c *MockClient) RecvWithTimeout(dur time.Duration) (*pbpeering.ReplicationMessage, error) { - select { - case err := <-c.ErrCh: - return nil, err - case r := <-c.ReplicationStream.sendCh: - return r, nil - case <-time.After(dur): - return nil, io.EOF - } -} - -func (c *MockClient) Close() { - close(c.ReplicationStream.recvCh) -} - -func NewMockClient(ctx context.Context) *MockClient { - return &MockClient{ - ReplicationStream: newTestReplicationStream(ctx), - } -} - -// MockStream mocks peering.PeeringService_StreamResourcesServer -type MockStream struct { - sendCh chan *pbpeering.ReplicationMessage - recvCh chan *pbpeering.ReplicationMessage - - ctx context.Context - mu sync.Mutex -} - -var _ pbpeering.PeeringService_StreamResourcesServer = (*MockStream)(nil) - -func newTestReplicationStream(ctx context.Context) *MockStream { - return &MockStream{ - sendCh: make(chan *pbpeering.ReplicationMessage, 1), - recvCh: make(chan *pbpeering.ReplicationMessage, 1), - ctx: ctx, - } -} - -// Send implements pbpeering.PeeringService_StreamResourcesServer -func (s *MockStream) Send(r *pbpeering.ReplicationMessage) error { - s.sendCh <- r - return nil -} - -// Recv implements pbpeering.PeeringService_StreamResourcesServer -func (s *MockStream) Recv() (*pbpeering.ReplicationMessage, error) { - r := <-s.recvCh - if r == nil { - return nil, io.EOF - } - return r, nil -} - -// Context implements grpc.ServerStream and grpc.ClientStream -func (s *MockStream) Context() context.Context { - return s.ctx -} - -// SendMsg implements grpc.ServerStream and grpc.ClientStream -func (s *MockStream) SendMsg(m interface{}) error { - return nil -} - -// RecvMsg implements grpc.ServerStream and grpc.ClientStream -func (s *MockStream) RecvMsg(m interface{}) error { - return nil -} - -// SetHeader implements grpc.ServerStream -func (s *MockStream) SetHeader(metadata.MD) error { - return nil -} - -// SendHeader implements grpc.ServerStream -func (s *MockStream) SendHeader(metadata.MD) error { - return nil -} - -// SetTrailer implements grpc.ServerStream -func (s *MockStream) SetTrailer(metadata.MD) {} - -type incrementalTime struct { - base time.Time - next uint64 -} - -func (t *incrementalTime) Now() time.Time { - t.next++ - return t.base.Add(time.Duration(t.next) * time.Second) -} diff --git a/agent/setup.go b/agent/setup.go index 1e094f754d..9ac506ab67 100644 --- a/agent/setup.go +++ b/agent/setup.go @@ -18,8 +18,8 @@ import ( "github.com/hashicorp/consul/agent/consul/fsm" "github.com/hashicorp/consul/agent/consul/stream" "github.com/hashicorp/consul/agent/consul/usagemetrics" - grpc "github.com/hashicorp/consul/agent/grpc/private" - "github.com/hashicorp/consul/agent/grpc/private/resolver" + grpc "github.com/hashicorp/consul/agent/grpc-internal" + "github.com/hashicorp/consul/agent/grpc-internal/resolver" "github.com/hashicorp/consul/agent/local" "github.com/hashicorp/consul/agent/pool" "github.com/hashicorp/consul/agent/router" diff --git a/agent/submatview/store_integration_test.go b/agent/submatview/store_integration_test.go index 8804a5cbf2..775b6f0b66 100644 --- a/agent/submatview/store_integration_test.go +++ b/agent/submatview/store_integration_test.go @@ -22,7 +22,7 @@ import ( "github.com/hashicorp/consul/agent/cache" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" - "github.com/hashicorp/consul/agent/grpc/private/services/subscribe" + "github.com/hashicorp/consul/agent/grpc-internal/services/subscribe" "github.com/hashicorp/consul/agent/rpcclient/health" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/submatview" diff --git a/agent/xds/clusters.go b/agent/xds/clusters.go index 3f2efdef7e..b4f4eea39b 100644 --- a/agent/xds/clusters.go +++ b/agent/xds/clusters.go @@ -98,7 +98,8 @@ func (s *ResourceGenerator) clustersFromSnapshotConnectProxy(cfgSnap *proxycfg.C upstream := cfgSnap.ConnectProxy.UpstreamConfig[uid] explicit := upstream.HasLocalPortOrSocket() - if _, implicit := cfgSnap.ConnectProxy.IntentionUpstreams[uid]; !implicit && !explicit { + implicit := cfgSnap.ConnectProxy.IsImplicitUpstream(uid) + if !implicit && !explicit { // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. continue } @@ -129,13 +130,12 @@ func (s *ResourceGenerator) clustersFromSnapshotConnectProxy(cfgSnap *proxycfg.C // NOTE: Any time we skip an upstream below we MUST also skip that same // upstream in endpoints.go so that the sets of endpoints generated matches // the sets of clusters. - // - // TODO(peering): make this work for tproxy for _, uid := range cfgSnap.ConnectProxy.PeeredUpstreamIDs() { upstreamCfg := cfgSnap.ConnectProxy.UpstreamConfig[uid] explicit := upstreamCfg.HasLocalPortOrSocket() - if _, implicit := cfgSnap.ConnectProxy.IntentionUpstreams[uid]; !implicit && !explicit { + implicit := cfgSnap.ConnectProxy.IsImplicitUpstream(uid) + if !implicit && !explicit { // Not associated with a known explicit or implicit upstream so it is skipped. continue } @@ -425,6 +425,24 @@ func (s *ResourceGenerator) makeGatewayServiceClusters( } clusters = append(clusters, cluster) + svcConfig, ok := cfgSnap.TerminatingGateway.ServiceConfigs[svc] + isHTTP2 := false + if ok { + upstreamCfg, err := structs.ParseUpstreamConfig(svcConfig.ProxyConfig) + if err != nil { + // Don't hard fail on a config typo, just warn. The parse func returns + // default config if there is an error so it's safe to continue. + s.Logger.Warn("failed to parse", "upstream", svc, "error", err) + } + isHTTP2 = upstreamCfg.Protocol == "http2" || upstreamCfg.Protocol == "grpc" + } + + if isHTTP2 { + if err := s.setHttp2ProtocolOptions(cluster); err != nil { + return nil, err + } + } + // If there is a service-resolver for this service then also setup a cluster for each subset for name, subset := range resolver.Subsets { subsetHostnameEndpoints, err := s.filterSubsetEndpoints(&subset, hostnameEndpoints) @@ -444,6 +462,11 @@ func (s *ResourceGenerator) makeGatewayServiceClusters( if err := s.injectGatewayServiceAddons(cfgSnap, cluster, svc, loadBalancer); err != nil { return nil, err } + if isHTTP2 { + if err := s.setHttp2ProtocolOptions(cluster); err != nil { + return nil, err + } + } clusters = append(clusters, cluster) } } @@ -706,11 +729,12 @@ func (s *ResourceGenerator) makeUpstreamClusterForPeerService( }, } } else { + ep, _ := cfgSnap.ConnectProxy.PeerUpstreamEndpoints.Get(uid) configureClusterWithHostnames( s.Logger, c, "", /*TODO:make configurable?*/ - cfgSnap.ConnectProxy.PeerUpstreamEndpoints[uid], + ep, true, /*isRemote*/ false, /*onlyPassing*/ ) @@ -720,7 +744,8 @@ func (s *ResourceGenerator) makeUpstreamClusterForPeerService( rootPEMs := cfgSnap.RootPEMs() if uid.Peer != "" { - rootPEMs = cfgSnap.ConnectProxy.UpstreamPeerTrustBundles[uid.Peer].ConcatenatedRootPEMs() + tbs, _ := cfgSnap.ConnectProxy.UpstreamPeerTrustBundles.Get(uid.Peer) + rootPEMs = tbs.ConcatenatedRootPEMs() } // Enable TLS upstream with the configured client certificate. @@ -907,6 +932,14 @@ func (s *ResourceGenerator) makeUpstreamClustersForDiscoveryChain( target := chain.Targets[targetID] + if forMeshGateway && !cfgSnap.Locality.Matches(target.Datacenter, target.Partition) { + s.Logger.Warn("ignoring discovery chain target that crosses a datacenter or partition boundary in a mesh gateway", + "target", target, + "gatewayLocality", cfgSnap.Locality, + ) + continue + } + // Determine if we have to generate the entire cluster differently. failoverThroughMeshGateway := chain.WillFailoverThroughMeshGateway(node) && !forMeshGateway @@ -1046,13 +1079,9 @@ func (s *ResourceGenerator) makeUpstreamClustersForDiscoveryChain( } if configureTLS { - rootPEMs := cfgSnap.RootPEMs() - if uid.Peer != "" { - rootPEMs = cfgSnap.ConnectProxy.UpstreamPeerTrustBundles[uid.Peer].ConcatenatedRootPEMs() - } commonTLSContext := makeCommonTLSContext( cfgSnap.Leaf(), - rootPEMs, + cfgSnap.RootPEMs(), makeTLSParametersFromProxyTLSConfig(cfgSnap.MeshConfigTLSOutgoing()), ) diff --git a/agent/xds/clusters_test.go b/agent/xds/clusters_test.go index b3e85486b7..49d333750c 100644 --- a/agent/xds/clusters_test.go +++ b/agent/xds/clusters_test.go @@ -589,6 +589,14 @@ func TestClustersFromSnapshot(t *testing.T) { name: "terminating-gateway-sni", create: proxycfg.TestConfigSnapshotTerminatingGatewaySNI, }, + { + name: "terminating-gateway-http2-upstream", + create: proxycfg.TestConfigSnapshotTerminatingGatewayHTTP2, + }, + { + name: "terminating-gateway-http2-upstream-subsets", + create: proxycfg.TestConfigSnapshotTerminatingGatewaySubsetsHTTP2, + }, { name: "terminating-gateway-ignore-extra-resolvers", create: proxycfg.TestConfigSnapshotTerminatingGatewayIgnoreExtraResolvers, diff --git a/agent/xds/delta.go b/agent/xds/delta.go index cdc6e53d6d..701c04f2ed 100644 --- a/agent/xds/delta.go +++ b/agent/xds/delta.go @@ -21,7 +21,7 @@ import ( "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/serverlessplugin" @@ -253,7 +253,7 @@ func (s *Server) processDelta(stream ADSDeltaStream, reqCh <-chan *envoy_discove // Start watching config for that proxy var err error - stateCh, watchCancel, err = s.CfgSrc.Watch(proxyID, nodeName, public.TokenFromContext(stream.Context())) + stateCh, watchCancel, err = s.CfgSrc.Watch(proxyID, nodeName, external.TokenFromContext(stream.Context())) if err != nil { return status.Errorf(codes.Internal, "failed to watch proxy service: %s", err) } diff --git a/agent/xds/endpoints.go b/agent/xds/endpoints.go index aca8760d37..2538914dd2 100644 --- a/agent/xds/endpoints.go +++ b/agent/xds/endpoints.go @@ -47,7 +47,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg. // TODO: this estimate is wrong resources := make([]proto.Message, 0, len(cfgSnap.ConnectProxy.PreparedQueryEndpoints)+ - len(cfgSnap.ConnectProxy.PeerUpstreamEndpoints)+ + cfgSnap.ConnectProxy.PeerUpstreamEndpoints.Len()+ len(cfgSnap.ConnectProxy.WatchedUpstreamEndpoints)) // NOTE: Any time we skip a chain below we MUST also skip that discovery chain in clusters.go @@ -56,7 +56,8 @@ func (s *ResourceGenerator) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg. upstream := cfgSnap.ConnectProxy.UpstreamConfig[uid] explicit := upstream.HasLocalPortOrSocket() - if _, implicit := cfgSnap.ConnectProxy.IntentionUpstreams[uid]; !implicit && !explicit { + implicit := cfgSnap.ConnectProxy.IsImplicitUpstream(uid) + if !implicit && !explicit { // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. continue } @@ -84,13 +85,12 @@ func (s *ResourceGenerator) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg. // NOTE: Any time we skip an upstream below we MUST also skip that same // upstream in clusters.go so that the sets of endpoints generated matches // the sets of clusters. - // - // TODO(peering): make this work for tproxy for _, uid := range cfgSnap.ConnectProxy.PeeredUpstreamIDs() { upstreamCfg := cfgSnap.ConnectProxy.UpstreamConfig[uid] explicit := upstreamCfg.HasLocalPortOrSocket() - if _, implicit := cfgSnap.ConnectProxy.IntentionUpstreams[uid]; !implicit && !explicit { + implicit := cfgSnap.ConnectProxy.IsImplicitUpstream(uid) + if !implicit && !explicit { // Not associated with a known explicit or implicit upstream so it is skipped. continue } @@ -110,7 +110,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotConnectProxy(cfgSnap *proxycfg. continue } - endpoints, ok := cfgSnap.ConnectProxy.PeerUpstreamEndpoints[uid] + endpoints, ok := cfgSnap.ConnectProxy.PeerUpstreamEndpoints.Get(uid) if ok { la := makeLoadAssignment( clusterName, @@ -177,7 +177,6 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C keys := cfgSnap.MeshGateway.GatewayKeys() resources := make([]proto.Message, 0, len(keys)+len(cfgSnap.MeshGateway.ServiceGroups)) - endpointsPerRemoteGateway := make(map[string]structs.CheckServiceNodes) for _, key := range keys { if key.Matches(cfgSnap.Datacenter, cfgSnap.ProxyID.PartitionOrDefault()) { continue // skip local @@ -194,8 +193,6 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C continue } - endpointsPerRemoteGateway[key.String()] = endpoints - { // standard connect clusterName := connect.GatewaySNI(key.Datacenter, key.Partition, cfgSnap.Roots.TrustDomain) @@ -274,7 +271,7 @@ func (s *ResourceGenerator) endpointsFromSnapshotMeshGateway(cfgSnap *proxycfg.C resources = append(resources, e...) // Generate the endpoints for exported discovery chain targets. - e, err = s.makeExportedUpstreamEndpointsForMeshGateway(cfgSnap, endpointsPerRemoteGateway) + e, err = s.makeExportedUpstreamEndpointsForMeshGateway(cfgSnap) if err != nil { return nil, err } @@ -479,6 +476,7 @@ func (s *ResourceGenerator) endpointsFromDiscoveryChain( gatewayEndpoints, targetID, gatewayKey, + forMeshGateway, ) if !valid { continue // skip the cluster if we're still populating the snapshot @@ -500,6 +498,7 @@ func (s *ResourceGenerator) endpointsFromDiscoveryChain( gatewayEndpoints, failTargetID, gatewayKey, + forMeshGateway, ) if !valid { continue // skip the failover target if we're still populating the snapshot @@ -519,10 +518,7 @@ func (s *ResourceGenerator) endpointsFromDiscoveryChain( return resources, nil } -func (s *ResourceGenerator) makeExportedUpstreamEndpointsForMeshGateway( - cfgSnap *proxycfg.ConfigSnapshot, - endpointsPerRemoteGateway map[string]structs.CheckServiceNodes, -) ([]proto.Message, error) { +func (s *ResourceGenerator) makeExportedUpstreamEndpointsForMeshGateway(cfgSnap *proxycfg.ConfigSnapshot) ([]proto.Message, error) { var resources []proto.Message populatedExportedClusters := make(map[string]struct{}) // key=clusterName @@ -531,41 +527,38 @@ func (s *ResourceGenerator) makeExportedUpstreamEndpointsForMeshGateway( chainEndpoints := make(map[string]structs.CheckServiceNodes) for _, target := range chain.Targets { - if cfgSnap.Locality.Matches(target.Datacenter, target.Partition) { - // served locally - targetSvc := target.ServiceName() + if !cfgSnap.Locality.Matches(target.Datacenter, target.Partition) { + s.Logger.Warn("ignoring discovery chain target that crosses a datacenter or partition boundary in a mesh gateway", + "target", target, + "gatewayLocality", cfgSnap.Locality, + ) + continue + } - endpoints, ok := cfgSnap.MeshGateway.ServiceGroups[targetSvc] + targetSvc := target.ServiceName() + + endpoints, ok := cfgSnap.MeshGateway.ServiceGroups[targetSvc] + if !ok { + continue // ignore; not ready + } + + if target.ServiceSubset == "" { + chainEndpoints[target.ID] = endpoints + } else { + resolver, ok := cfgSnap.MeshGateway.ServiceResolvers[targetSvc] + if !ok { + continue // ignore; not ready + } + subset, ok := resolver.Subsets[target.ServiceSubset] if !ok { continue // ignore; not ready } - if target.ServiceSubset == "" { - chainEndpoints[target.ID] = endpoints - } else { - resolver, ok := cfgSnap.MeshGateway.ServiceResolvers[targetSvc] - if !ok { - continue // ignore; not ready - } - subset, ok := resolver.Subsets[target.ServiceSubset] - if !ok { - continue // ignore; not ready - } - - subsetEndpoints, err := s.filterSubsetEndpoints(&subset, endpoints) - if err != nil { - return nil, err - } - chainEndpoints[target.ID] = subsetEndpoints + subsetEndpoints, err := s.filterSubsetEndpoints(&subset, endpoints) + if err != nil { + return nil, err } - } else { - // serve remotely - gk := proxycfg.GatewayKey{ - Datacenter: target.Datacenter, - Partition: target.Partition, - } - // TODO(peering): handle hostname endpoints logic - chainEndpoints[target.ID] = cfgSnap.GetMeshGatewayEndpoints(gk) + chainEndpoints[target.ID] = subsetEndpoints } } @@ -575,7 +568,7 @@ func (s *ResourceGenerator) makeExportedUpstreamEndpointsForMeshGateway( cfgSnap.Locality, nil, chainEndpoints, - endpointsPerRemoteGateway, + nil, true, ) if err != nil { @@ -652,6 +645,7 @@ func makeLoadAssignmentEndpointGroup( gatewayHealth map[string]structs.CheckServiceNodes, targetID string, localKey proxycfg.GatewayKey, + forMeshGateway bool, ) (loadAssignmentEndpointGroup, bool) { realEndpoints, ok := targetHealth[targetID] if !ok { @@ -666,12 +660,11 @@ func makeLoadAssignmentEndpointGroup( case structs.MeshGatewayModeRemote: gatewayKey.Datacenter = target.Datacenter gatewayKey.Partition = target.Partition - case structs.MeshGatewayModeLocal: gatewayKey = localKey } - if gatewayKey.IsEmpty() || localKey.Matches(target.Datacenter, target.Partition) { + if forMeshGateway || gatewayKey.IsEmpty() || localKey.Matches(target.Datacenter, target.Partition) { // Gateways are not needed if the request isn't for a remote DC or partition. return loadAssignmentEndpointGroup{ Endpoints: realEndpoints, diff --git a/agent/xds/listeners.go b/agent/xds/listeners.go index 1bf8e4e6c4..2f3650aa77 100644 --- a/agent/xds/listeners.go +++ b/agent/xds/listeners.go @@ -110,7 +110,8 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. upstreamCfg := cfgSnap.ConnectProxy.UpstreamConfig[uid] explicit := upstreamCfg.HasLocalPortOrSocket() - if _, implicit := cfgSnap.ConnectProxy.IntentionUpstreams[uid]; !implicit && !explicit { + implicit := cfgSnap.ConnectProxy.IsImplicitUpstream(uid) + if !implicit && !explicit { // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. continue } @@ -228,13 +229,12 @@ func (s *ResourceGenerator) listenersFromSnapshotConnectProxy(cfgSnap *proxycfg. // Looping over explicit upstreams is only needed for cross-peer because // they do not have discovery chains. - // - // TODO(peering): make this work for tproxy for _, uid := range cfgSnap.ConnectProxy.PeeredUpstreamIDs() { upstreamCfg := cfgSnap.ConnectProxy.UpstreamConfig[uid] explicit := upstreamCfg.HasLocalPortOrSocket() - if _, implicit := cfgSnap.ConnectProxy.IntentionUpstreams[uid]; !implicit && !explicit { + implicit := cfgSnap.ConnectProxy.IsImplicitUpstream(uid) + if !implicit && !explicit { // Not associated with a known explicit or implicit upstream so it is skipped. continue } diff --git a/agent/xds/routes.go b/agent/xds/routes.go index 6f9e2214c1..6faa1fa674 100644 --- a/agent/xds/routes.go +++ b/agent/xds/routes.go @@ -50,7 +50,8 @@ func (s *ResourceGenerator) routesForConnectProxy(cfgSnap *proxycfg.ConfigSnapsh } explicit := cfgSnap.ConnectProxy.UpstreamConfig[uid].HasLocalPortOrSocket() - if _, implicit := cfgSnap.ConnectProxy.IntentionUpstreams[uid]; !implicit && !explicit { + implicit := cfgSnap.ConnectProxy.IsImplicitUpstream(uid) + if !implicit && !explicit { // Discovery chain is not associated with a known explicit or implicit upstream so it is skipped. continue } diff --git a/agent/xds/server.go b/agent/xds/server.go index adbe9a62f7..cc27f3fde7 100644 --- a/agent/xds/server.go +++ b/agent/xds/server.go @@ -16,7 +16,7 @@ import ( "google.golang.org/grpc/status" "github.com/hashicorp/consul/acl" - "github.com/hashicorp/consul/agent/grpc/public" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/agent/xds/xdscommon" @@ -201,7 +201,7 @@ func (s *Server) authorize(ctx context.Context, cfgSnap *proxycfg.ConfigSnapshot return status.Errorf(codes.Unauthenticated, "unauthenticated: no config snapshot") } - authz, err := s.ResolveToken(public.TokenFromContext(ctx)) + authz, err := s.ResolveToken(external.TokenFromContext(ctx)) if acl.IsErrNotFound(err) { return status.Errorf(codes.Unauthenticated, "unauthenticated: %v", err) } else if acl.IsErrPermissionDenied(err) { diff --git a/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden b/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden index c65f4f9c17..8c85bbc827 100644 --- a/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden +++ b/agent/xds/testdata/clusters/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden @@ -35,23 +35,6 @@ } }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": { - - }, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "outlierDetection": { - - } - }, { "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", "name": "exported~alt.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", @@ -110,64 +93,6 @@ } } }, - { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "exported~api.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", - "altStatName": "exported~api.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", - "type": "EDS", - "edsClusterConfig": { - "edsConfig": { - "ads": { - - }, - "resourceApiVersion": "V3" - } - }, - "connectTimeout": "5s", - "circuitBreakers": { - - }, - "outlierDetection": { - - }, - "commonLbConfig": { - "healthyPanicThreshold": { - - } - }, - "transportSocket": { - "name": "tls", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "commonTlsContext": { - "tlsParams": { - - }, - "tlsCertificates": [ - { - "certificateChain": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" - }, - "privateKey": { - "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" - } - } - ], - "validationContext": { - "trustedCa": { - "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" - }, - "matchSubjectAltNames": [ - { - "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc2/svc/api" - } - ] - } - }, - "sni": "api.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - }, { "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", "name": "exported~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", @@ -225,6 +150,64 @@ "sni": "db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" } } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "exported~v2.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "altStatName": "exported~v2.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "EDS", + "edsClusterConfig": { + "edsConfig": { + "ads": { + + }, + "resourceApiVersion": "V3" + } + }, + "connectTimeout": "5s", + "circuitBreakers": { + + }, + "outlierDetection": { + + }, + "commonLbConfig": { + "healthyPanicThreshold": { + + } + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "tlsCertificates": [ + { + "certificateChain": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICjDCCAjKgAwIBAgIIC5llxGV1gB8wCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowDjEMMAoG\nA1UEAxMDd2ViMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEADPv1RHVNRfa2VKR\nAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Favq5E0ivpNtv1QnFhxtPd7d5k4e+T7\nSkW1TaOCAXIwggFuMA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggrBgEFBQcD\nAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADBoBgNVHQ4EYQRfN2Q6MDc6ODc6M2E6\nNDA6MTk6NDc6YzM6NWE6YzA6YmE6NjI6ZGY6YWY6NGI6ZDQ6MDU6MjU6NzY6M2Q6\nNWE6OGQ6MTY6OGQ6Njc6NWU6MmU6YTA6MzQ6N2Q6ZGM6ZmYwagYDVR0jBGMwYYBf\nZDE6MTE6MTE6YWM6MmE6YmE6OTc6YjI6M2Y6YWM6N2I6YmQ6ZGE6YmU6YjE6OGE6\nZmM6OWE6YmE6YjU6YmM6ODM6ZTc6NWU6NDE6NmY6ZjI6NzM6OTU6NTg6MGM6ZGIw\nWQYDVR0RBFIwUIZOc3BpZmZlOi8vMTExMTExMTEtMjIyMi0zMzMzLTQ0NDQtNTU1\nNTU1NTU1NTU1LmNvbnN1bC9ucy9kZWZhdWx0L2RjL2RjMS9zdmMvd2ViMAoGCCqG\nSM49BAMCA0gAMEUCIGC3TTvvjj76KMrguVyFf4tjOqaSCRie3nmHMRNNRav7AiEA\npY0heYeK9A6iOLrzqxSerkXXQyj5e9bE4VgUnxgPU6g=\n-----END CERTIFICATE-----\n" + }, + "privateKey": { + "inlineString": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIMoTkpRggp3fqZzFKh82yS4LjtJI+XY+qX/7DefHFrtdoAoGCCqGSM49\nAwEHoUQDQgAEADPv1RHVNRfa2VKRAB16b6rZnEt7tuhaxCFpQXPj7M2omb0B9Fav\nq5E0ivpNtv1QnFhxtPd7d5k4e+T7SkW1TQ==\n-----END EC PRIVATE KEY-----\n" + } + } + ], + "validationContext": { + "trustedCa": { + "inlineString": "-----BEGIN CERTIFICATE-----\nMIICXDCCAgKgAwIBAgIICpZq70Z9LyUwCgYIKoZIzj0EAwIwFDESMBAGA1UEAxMJ\nVGVzdCBDQSAyMB4XDTE5MDMyMjEzNTgyNloXDTI5MDMyMjEzNTgyNlowFDESMBAG\nA1UEAxMJVGVzdCBDQSAyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEIhywH1gx\nAsMwuF3ukAI5YL2jFxH6Usnma1HFSfVyxbXX1/uoZEYrj8yCAtdU2yoHETyd+Zx2\nThhRLP79pYegCaOCATwwggE4MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTAD\nAQH/MGgGA1UdDgRhBF9kMToxMToxMTphYzoyYTpiYTo5NzpiMjozZjphYzo3Yjpi\nZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1ZTo0MTo2ZjpmMjo3\nMzo5NTo1ODowYzpkYjBqBgNVHSMEYzBhgF9kMToxMToxMTphYzoyYTpiYTo5Nzpi\nMjozZjphYzo3YjpiZDpkYTpiZTpiMTo4YTpmYzo5YTpiYTpiNTpiYzo4MzplNzo1\nZTo0MTo2ZjpmMjo3Mzo5NTo1ODowYzpkYjA/BgNVHREEODA2hjRzcGlmZmU6Ly8x\nMTExMTExMS0yMjIyLTMzMzMtNDQ0NC01NTU1NTU1NTU1NTUuY29uc3VsMAoGCCqG\nSM49BAMCA0gAMEUCICOY0i246rQHJt8o8Oya0D5PLL1FnmsQmQqIGCi31RwnAiEA\noR5f6Ku+cig2Il8T8LJujOp2/2A72QcHZA57B13y+8o=\n-----END CERTIFICATE-----\n" + }, + "matchSubjectAltNames": [ + { + "exact": "spiffe://11111111-2222-3333-4444-555555555555.consul/ns/default/dc/dc1/svc/api" + } + ] + } + }, + "sni": "v2.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" + } + } } ], "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", diff --git a/agent/xds/testdata/clusters/terminating-gateway-http2-upstream-subsets.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-http2-upstream-subsets.latest.golden new file mode 100644 index 0000000000..953a207e68 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-http2-upstream-subsets.latest.golden @@ -0,0 +1,181 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "LOGICAL_DNS", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "v1.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "web.external.service", + "portValue": 9090 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": { + + } + } + } + }, + "dnsRefreshRate": "10s", + "dnsLookupFamily": "V4_ONLY", + "outlierDetection": { + + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "LOGICAL_DNS", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "v2.web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "web.external2.service", + "portValue": 9091 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": { + + } + } + } + }, + "dnsRefreshRate": "10s", + "dnsLookupFamily": "V4_ONLY", + "outlierDetection": { + + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + } + }, + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "LOGICAL_DNS", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "web.external.service", + "portValue": 9090 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": { + + } + } + } + }, + "dnsRefreshRate": "10s", + "dnsLookupFamily": "V4_ONLY", + "outlierDetection": { + + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/clusters/terminating-gateway-http2-upstream.latest.golden b/agent/xds/testdata/clusters/terminating-gateway-http2-upstream.latest.golden new file mode 100644 index 0000000000..9a8e2bdf43 --- /dev/null +++ b/agent/xds/testdata/clusters/terminating-gateway-http2-upstream.latest.golden @@ -0,0 +1,65 @@ +{ + "versionInfo": "00000001", + "resources": [ + { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "type": "LOGICAL_DNS", + "connectTimeout": "5s", + "loadAssignment": { + "clusterName": "web.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", + "endpoints": [ + { + "lbEndpoints": [ + { + "endpoint": { + "address": { + "socketAddress": { + "address": "web.external.service", + "portValue": 9090 + } + } + }, + "healthStatus": "HEALTHY", + "loadBalancingWeight": 1 + } + ] + } + ] + }, + "typedExtensionProtocolOptions": { + "envoy.extensions.upstreams.http.v3.HttpProtocolOptions": { + "@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "explicitHttpConfig": { + "http2ProtocolOptions": { + + } + } + } + }, + "dnsRefreshRate": "10s", + "dnsLookupFamily": "V4_ONLY", + "outlierDetection": { + + }, + "transportSocket": { + "name": "tls", + "typedConfig": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "commonTlsContext": { + "tlsParams": { + + }, + "validationContext": { + "trustedCa": { + "filename": "ca.cert.pem" + } + } + } + } + } + } + ], + "typeUrl": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "nonce": "00000001" +} \ No newline at end of file diff --git a/agent/xds/testdata/endpoints/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden b/agent/xds/testdata/endpoints/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden index da1e19b7b6..b993f6a71e 100644 --- a/agent/xds/testdata/endpoints/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden +++ b/agent/xds/testdata/endpoints/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden @@ -69,40 +69,6 @@ } ] }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "dc2.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "198.18.1.1", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "198.18.1.2", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, { "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", "clusterName": "exported~alt.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", @@ -137,40 +103,6 @@ } ] }, - { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "clusterName": "exported~api.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul", - "endpoints": [ - { - "lbEndpoints": [ - { - "endpoint": { - "address": { - "socketAddress": { - "address": "198.18.1.1", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - }, - { - "endpoint": { - "address": { - "socketAddress": { - "address": "198.18.1.2", - "portValue": 443 - } - } - }, - "healthStatus": "HEALTHY", - "loadBalancingWeight": 1 - } - ] - } - ] - }, { "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", "clusterName": "exported~db.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul", diff --git a/agent/xds/testdata/listeners/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden b/agent/xds/testdata/listeners/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden index b89506084d..1ed34afb91 100644 --- a/agent/xds/testdata/listeners/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden +++ b/agent/xds/testdata/listeners/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden @@ -101,23 +101,6 @@ } } }, - { - "filterChainMatch": { - "serverNames": [ - "*.dc2.internal.11111111-2222-3333-4444-555555555555.consul" - ] - }, - "filters": [ - { - "name": "envoy.filters.network.tcp_proxy", - "typedConfig": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", - "statPrefix": "mesh_gateway_remote.default.dc2", - "cluster": "dc2.internal.11111111-2222-3333-4444-555555555555.consul" - } - } - ] - }, { "filters": [ { diff --git a/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden b/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden index d504294d02..ce1c0ad2d5 100644 --- a/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden +++ b/agent/xds/testdata/routes/mesh-gateway-with-exported-peered-services-http-with-router.latest.golden @@ -36,7 +36,7 @@ "prefix": "/api" }, "route": { - "cluster": "exported~api.default.dc2.internal.11111111-2222-3333-4444-555555555555.consul" + "cluster": "exported~v2.api.default.dc1.internal.11111111-2222-3333-4444-555555555555.consul" } }, { diff --git a/command/config/delete/config_delete.go b/command/config/delete/config_delete.go index 913d09e85f..caa21c0947 100644 --- a/command/config/delete/config_delete.go +++ b/command/config/delete/config_delete.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/hashicorp/consul/command/flags" + "github.com/hashicorp/consul/command/helpers" "github.com/mitchellh/cli" ) @@ -25,10 +26,13 @@ type cmd struct { name string cas bool modifyIndex uint64 + filename string } func (c *cmd) init() { c.flags = flag.NewFlagSet("", flag.ContinueOnError) + + c.flags.StringVar(&c.filename, "filename", "", "The filename of the config entry to delete") c.flags.StringVar(&c.kind, "kind", "", "The kind of configuration to delete.") c.flags.StringVar(&c.name, "name", "", "The name of configuration to delete.") c.flags.BoolVar(&c.cas, "cas", false, @@ -55,6 +59,25 @@ func (c *cmd) Run(args []string) int { return 1 } + kind := c.kind + name := c.name + var err error + if c.filename != "" { + data, err := helpers.LoadDataSourceNoRaw(c.filename, nil) + if err != nil { + c.UI.Error(fmt.Sprintf("Failed to load data: %v", err)) + return 1 + } + + entry, err := helpers.ParseConfigEntry(data) + if err != nil { + c.UI.Error(fmt.Sprintf("Failed to decode config entry input: %v", err)) + return 1 + } + kind = entry.GetKind() + name = entry.GetName() + } + client, err := c.http.APIClient() if err != nil { c.UI.Error(fmt.Sprintf("Error connect to Consul agent: %s", err)) @@ -64,33 +87,58 @@ func (c *cmd) Run(args []string) int { var deleted bool if c.cas { - deleted, _, err = entries.DeleteCAS(c.kind, c.name, c.modifyIndex, nil) + deleted, _, err = entries.DeleteCAS(kind, name, c.modifyIndex, nil) } else { - _, err = entries.Delete(c.kind, c.name, nil) + _, err = entries.Delete(kind, name, nil) deleted = err == nil } if err != nil { - c.UI.Error(fmt.Sprintf("Error deleting config entry %s/%s: %v", c.kind, c.name, err)) + c.UI.Error(fmt.Sprintf("Error deleting config entry %s/%s: %v", kind, name, err)) return 1 } if !deleted { - c.UI.Error(fmt.Sprintf("Config entry not deleted: %s/%s", c.kind, c.name)) + c.UI.Error(fmt.Sprintf("Config entry not deleted: %s/%s", kind, name)) return 1 } - c.UI.Info(fmt.Sprintf("Config entry deleted: %s/%s", c.kind, c.name)) + c.UI.Info(fmt.Sprintf("Config entry deleted: %s/%s", kind, name)) return 0 } func (c *cmd) validateArgs() error { - if c.kind == "" { - return errors.New("Must specify the -kind parameter") + count := 0 + if c.filename != "" { + count++ } - if c.name == "" { - return errors.New("Must specify the -name parameter") + if c.kind != "" { + count++ + } + + if c.name != "" { + count++ + } + + if count >= 3 { + return errors.New("filename can't be used with kind or name") + } else if count == 0 { + return errors.New("Must specify the -kind or -filename parameter") + } + + if c.filename != "" { + if count == 2 { + return errors.New("filename can't be used with kind or name") + } + } else { + if c.kind == "" { + return errors.New("Must specify the -kind parameter") + } + + if c.name == "" { + return errors.New("Must specify the -name parameter") + } } if c.cas && c.modifyIndex == 0 { @@ -115,12 +163,13 @@ func (c *cmd) Help() string { const ( synopsis = "Delete a centralized config entry" help = ` -Usage: consul config delete [options] -kind -name +Usage: consul config delete [options] ([-kind -name ] | [-f FILENAME]) Deletes the configuration entry specified by the kind and name. Example: $ consul config delete -kind service-defaults -name web + $ consul config delete -filename service-defaults-web.hcl ` ) diff --git a/command/config/delete/config_delete_test.go b/command/config/delete/config_delete_test.go index 01c00b549b..d4f9b704ed 100644 --- a/command/config/delete/config_delete_test.go +++ b/command/config/delete/config_delete_test.go @@ -6,6 +6,7 @@ import ( "github.com/hashicorp/consul/agent" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil" "github.com/mitchellh/cli" "github.com/stretchr/testify/require" ) @@ -30,11 +31,7 @@ func TestConfigDelete(t *testing.T) { ui := cli.NewMockUi() c := New(ui) - _, _, err := client.ConfigEntries().Set(&api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: "web", - Protocol: "tcp", - }, nil) + err := createEntry(client) require.NoError(t, err) args := []string{ @@ -54,6 +51,15 @@ func TestConfigDelete(t *testing.T) { require.Nil(t, entry) } +func createEntry(client *api.Client) error { + _, _, err := client.ConfigEntries().Set(&api.ServiceConfigEntry{ + Kind: api.ServiceDefaults, + Name: "web", + Protocol: "tcp", + }, nil) + return err +} + func TestConfigDelete_CAS(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short") @@ -65,11 +71,7 @@ func TestConfigDelete_CAS(t *testing.T) { defer a.Shutdown() client := a.Client() - _, _, err := client.ConfigEntries().Set(&api.ServiceConfigEntry{ - Kind: api.ServiceDefaults, - Name: "web", - Protocol: "tcp", - }, nil) + err := createEntry(client) require.NoError(t, err) entry, _, err := client.ConfigEntries().Get(api.ServiceDefaults, "web", nil) @@ -111,11 +113,44 @@ func TestConfigDelete_CAS(t *testing.T) { require.Contains(t, ui.OutputWriter.String(), "Config entry deleted: service-defaults/web") require.Empty(t, ui.ErrorWriter.String()) - entry, _, err := client.ConfigEntries().Get(api.ServiceDefaults, "web", nil) require.Error(t, err) require.Nil(t, entry) }) + + t.Run("delete from file with a valid modify index", func(t *testing.T) { + err := createEntry(client) + require.NoError(t, err) + entry, _, err := client.ConfigEntries().Get(api.ServiceDefaults, "web", nil) + require.NoError(t, err) + + ui := cli.NewMockUi() + c := New(ui) + f := testutil.TempFile(t, "config-write-svc-web.hcl") + _, err = f.WriteString(` + Kind = "service-defaults" + Name = "web" + Protocol = "tcp" + `) + require.NoError(t, err) + + args := []string{ + "-http-addr=" + a.HTTPAddr(), + "-filename=" + f.Name(), + "-cas", + "-modify-index=" + strconv.FormatUint(entry.GetModifyIndex(), 10), + } + + code := c.Run(args) + require.Equal(t, 0, code) + require.Contains(t, ui.OutputWriter.String(), + "Config entry deleted: service-defaults/web") + require.Empty(t, ui.ErrorWriter.String()) + + entry, _, err = client.ConfigEntries().Get(api.ServiceDefaults, "web", nil) + require.Error(t, err) + require.Nil(t, entry) + }) } func TestConfigDelete_InvalidArgs(t *testing.T) { @@ -125,8 +160,12 @@ func TestConfigDelete_InvalidArgs(t *testing.T) { args []string err string }{ - "no kind": { + "no kind or filename": { args: []string{}, + err: "Must specify the -kind or -filename parameter", + }, + "no kind": { + args: []string{"-name", "web"}, err: "Must specify the -kind parameter", }, "no name": { @@ -145,6 +184,18 @@ func TestConfigDelete_InvalidArgs(t *testing.T) { args: []string{"-kind", api.ServiceDefaults, "-name", "web", "-modify-index", "1"}, err: "Cannot specify -modify-index without -cas", }, + "kind and filename": { + args: []string{"-kind", api.ServiceDefaults, "-filename", "config-file.hcl"}, + err: "filename can't be used with kind or name", + }, + "name and filename": { + args: []string{"-name", "db", "-filename", "config-file.hcl"}, + err: "filename can't be used with kind or name", + }, + "kind, name, and filename": { + args: []string{"-kind", api.ServiceDefaults, "-name", "db", "-filename", "config-file.hcl"}, + err: "filename can't be used with kind or name", + }, } for name, tcase := range cases { diff --git a/command/config/write/config_write.go b/command/config/write/config_write.go index 9e08fde38a..0c377e6c45 100644 --- a/command/config/write/config_write.go +++ b/command/config/write/config_write.go @@ -66,7 +66,7 @@ func (c *cmd) Run(args []string) int { return 1 } - entry, err := parseConfigEntry(data) + entry, err := helpers.ParseConfigEntry(data) if err != nil { c.UI.Error(fmt.Sprintf("Failed to decode config entry input: %v", err)) return 1 @@ -100,16 +100,6 @@ func (c *cmd) Run(args []string) int { return 0 } -func parseConfigEntry(data string) (api.ConfigEntry, error) { - // parse the data - var raw map[string]interface{} - if err := hclDecode(&raw, data); err != nil { - return nil, fmt.Errorf("Failed to decode config entry input: %v", err) - } - - return newDecodeConfigEntry(raw) -} - // There is a 'structs' variation of this in // agent/structs/config_entry.go:DecodeConfigEntry func newDecodeConfigEntry(raw map[string]interface{}) (api.ConfigEntry, error) { diff --git a/command/config/write/config_write_test.go b/command/config/write/config_write_test.go index 566e2ab9b1..3ea5a8be2a 100644 --- a/command/config/write/config_write_test.go +++ b/command/config/write/config_write_test.go @@ -5,9 +5,6 @@ import ( "io" "strings" "testing" - "time" - - "github.com/hashicorp/consul/agent/structs" "github.com/mitchellh/cli" "github.com/stretchr/testify/require" @@ -152,3068 +149,7 @@ http { }) } -// TestParseConfigEntry is the 'api' mirror image of -// agent/structs/config_entry_test.go:TestDecodeConfigEntry -func TestParseConfigEntry(t *testing.T) { - t.Parallel() - for _, tc := range []struct { - name string - camel, camelJSON string - snake, snakeJSON string - expect api.ConfigEntry - expectJSON api.ConfigEntry - expectErr string - }{ - { - name: "proxy-defaults: extra fields or typo", - snake: ` - kind = "proxy-defaults" - name = "main" - cornfig { - "foo" = 19 - } - `, - camel: ` - Kind = "proxy-defaults" - Name = "main" - Cornfig { - "foo" = 19 - } - `, - snakeJSON: ` - { - "kind": "proxy-defaults", - "name": "main", - "cornfig": { - "foo": 19 - } - } - `, - camelJSON: ` - { - "Kind": "proxy-defaults", - "Name": "main", - "Cornfig": { - "foo": 19 - } - } - `, - expectErr: `invalid config key "cornfig"`, - }, - { - name: "proxy-defaults", - snake: ` - kind = "proxy-defaults" - name = "main" - meta { - "foo" = "bar" - "gir" = "zim" - } - config { - "foo" = 19 - "bar" = "abc" - "moreconfig" { - "moar" = "config" - } - } - mesh_gateway { - mode = "remote" - } - mode = "direct" - transparent_proxy = { - outbound_listener_port = 10101 - dialed_directly = true - } - `, - camel: ` - Kind = "proxy-defaults" - Name = "main" - Meta { - "foo" = "bar" - "gir" = "zim" - } - Config { - "foo" = 19 - "bar" = "abc" - "moreconfig" { - "moar" = "config" - } - } - MeshGateway { - Mode = "remote" - } - Mode = "direct" - TransparentProxy = { - outbound_listener_port = 10101 - dialed_directly = true - } - `, - snakeJSON: ` - { - "kind": "proxy-defaults", - "name": "main", - "meta" : { - "foo": "bar", - "gir": "zim" - }, - "config": { - "foo": 19, - "bar": "abc", - "moreconfig": { - "moar": "config" - } - }, - "mesh_gateway": { - "mode": "remote" - }, - "mode": "direct", - "transparent_proxy": { - "outbound_listener_port": 10101, - "dialed_directly": true - } - } - `, - camelJSON: ` - { - "Kind": "proxy-defaults", - "Name": "main", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "Config": { - "foo": 19, - "bar": "abc", - "moreconfig": { - "moar": "config" - } - }, - "MeshGateway": { - "Mode": "remote" - }, - "Mode": "direct", - "TransparentProxy": { - "OutboundListenerPort": 10101, - "DialedDirectly": true - } - } - `, - expect: &api.ProxyConfigEntry{ - Kind: "proxy-defaults", - Name: "main", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Config: map[string]interface{}{ - "foo": 19, - "bar": "abc", - "moreconfig": map[string]interface{}{ - "moar": "config", - }, - }, - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeRemote, - }, - Mode: api.ProxyModeDirect, - TransparentProxy: &api.TransparentProxyConfig{ - OutboundListenerPort: 10101, - DialedDirectly: true, - }, - }, - expectJSON: &api.ProxyConfigEntry{ - Kind: "proxy-defaults", - Name: "main", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Config: map[string]interface{}{ - "foo": float64(19), // json decoding gives float64 instead of int here - "bar": "abc", - "moreconfig": map[string]interface{}{ - "moar": "config", - }, - }, - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeRemote, - }, - Mode: api.ProxyModeDirect, - TransparentProxy: &api.TransparentProxyConfig{ - OutboundListenerPort: 10101, - DialedDirectly: true, - }, - }, - }, - { - name: "terminating-gateway", - snake: ` - kind = "terminating-gateway" - name = "terminating-gw-west" - namespace = "default" - meta { - "foo" = "bar" - "gir" = "zim" - } - services = [ - { - name = "billing" - namespace = "biz" - ca_file = "/etc/ca.crt" - cert_file = "/etc/client.crt" - key_file = "/etc/tls.key" - sni = "mydomain" - }, - { - name = "*" - namespace = "ops" - } - ] - `, - camel: ` - Kind = "terminating-gateway" - Name = "terminating-gw-west" - Namespace = "default" - Meta { - "foo" = "bar" - "gir" = "zim" - } - Services = [ - { - Name = "billing" - Namespace = "biz" - CAFile = "/etc/ca.crt" - CertFile = "/etc/client.crt" - KeyFile = "/etc/tls.key" - SNI = "mydomain" - }, - { - Name = "*" - Namespace = "ops" - } - ] - `, - snakeJSON: ` - { - "kind": "terminating-gateway", - "name": "terminating-gw-west", - "namespace": "default", - "meta" : { - "foo": "bar", - "gir": "zim" - }, - "services": [ - { - "name": "billing", - "namespace": "biz", - "ca_file": "/etc/ca.crt", - "cert_file": "/etc/client.crt", - "key_file": "/etc/tls.key", - "sni": "mydomain" - }, - { - "name": "*", - "namespace": "ops" - } - ] - } - `, - camelJSON: ` - { - "Kind": "terminating-gateway", - "Name": "terminating-gw-west", - "Namespace": "default", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "Services": [ - { - "Name": "billing", - "Namespace": "biz", - "CAFile": "/etc/ca.crt", - "CertFile": "/etc/client.crt", - "KeyFile": "/etc/tls.key", - "SNI": "mydomain" - }, - { - "Name": "*", - "Namespace": "ops" - } - ] - } - `, - expect: &api.TerminatingGatewayConfigEntry{ - Kind: "terminating-gateway", - Name: "terminating-gw-west", - Namespace: "default", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Services: []api.LinkedService{ - { - Name: "billing", - Namespace: "biz", - CAFile: "/etc/ca.crt", - CertFile: "/etc/client.crt", - KeyFile: "/etc/tls.key", - SNI: "mydomain", - }, - { - Name: "*", - Namespace: "ops", - }, - }, - }, - expectJSON: &api.TerminatingGatewayConfigEntry{ - Kind: "terminating-gateway", - Name: "terminating-gw-west", - Namespace: "default", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Services: []api.LinkedService{ - { - Name: "billing", - Namespace: "biz", - CAFile: "/etc/ca.crt", - CertFile: "/etc/client.crt", - KeyFile: "/etc/tls.key", - SNI: "mydomain", - }, - { - Name: "*", - Namespace: "ops", - }, - }, - }, - }, - { - name: "service-defaults: kitchen sink (upstreams edition)", - snake: ` - kind = "service-defaults" - name = "main" - meta { - "foo" = "bar" - "gir" = "zim" - } - protocol = "http" - external_sni = "abc-123" - mesh_gateway { - mode = "remote" - } - mode = "direct" - transparent_proxy = { - outbound_listener_port = 10101 - dialed_directly = true - } - upstream_config { - overrides = [ - { - name = "redis" - passive_health_check { - max_failures = 3 - interval = "2s" - } - envoy_listener_json = "{ \"listener-foo\": 5 }" - envoy_cluster_json = "{ \"cluster-bar\": 5 }" - protocol = "grpc" - connect_timeout_ms = 6543 - }, - { - name = "finance--billing" - mesh_gateway { - mode = "remote" - } - limits { - max_connections = 1111 - max_pending_requests = 2222 - max_concurrent_requests = 3333 - } - } - ] - defaults { - envoy_cluster_json = "zip" - envoy_listener_json = "zop" - connect_timeout_ms = 5000 - protocol = "http" - limits { - max_connections = 3 - max_pending_requests = 4 - max_concurrent_requests = 5 - } - passive_health_check { - max_failures = 5 - interval = "4s" - } - } - } - `, - camel: ` - Kind = "service-defaults" - Name = "main" - Meta { - "foo" = "bar" - "gir" = "zim" - } - Protocol = "http" - ExternalSNI = "abc-123" - MeshGateway { - Mode = "remote" - } - Mode = "direct" - TransparentProxy = { - outbound_listener_port = 10101 - dialed_directly = true - } - UpstreamConfig { - Overrides = [ - { - Name = "redis" - PassiveHealthCheck { - MaxFailures = 3 - Interval = "2s" - } - EnvoyListenerJson = "{ \"listener-foo\": 5 }" - EnvoyClusterJson = "{ \"cluster-bar\": 5 }" - Protocol = "grpc" - ConnectTimeoutMs = 6543 - }, - { - Name = "finance--billing" - MeshGateway { - Mode = "remote" - } - Limits { - MaxConnections = 1111 - MaxPendingRequests = 2222 - MaxConcurrentRequests = 3333 - } - } - ] - Defaults { - EnvoyClusterJson = "zip" - EnvoyListenerJson = "zop" - ConnectTimeoutMs = 5000 - Protocol = "http" - Limits { - MaxConnections = 3 - MaxPendingRequests = 4 - MaxConcurrentRequests = 5 - } - PassiveHealthCheck { - MaxFailures = 5 - Interval = "4s" - } - } - } - `, - snakeJSON: ` - { - "kind": "service-defaults", - "name": "main", - "meta" : { - "foo": "bar", - "gir": "zim" - }, - "protocol": "http", - "external_sni": "abc-123", - "mesh_gateway": { - "mode": "remote" - }, - "mode": "direct", - "transparent_proxy": { - "outbound_listener_port": 10101, - "dialed_directly": true - }, - "upstream_config": { - "overrides": [ - { - "name": "redis", - "passive_health_check": { - "max_failures": 3, - "interval": "2s" - }, - "envoy_listener_json": "{ \"listener-foo\": 5 }", - "envoy_cluster_json": "{ \"cluster-bar\": 5 }", - "protocol": "grpc", - "connect_timeout_ms": 6543 - }, - { - "name": "finance--billing", - "mesh_gateway": { - "mode": "remote" - }, - "limits": { - "max_connections": 1111, - "max_pending_requests": 2222, - "max_concurrent_requests": 3333 - } - } - ], - "defaults": { - "envoy_cluster_json": "zip", - "envoy_listener_json": "zop", - "connect_timeout_ms": 5000, - "protocol": "http", - "limits": { - "max_connections": 3, - "max_pending_requests": 4, - "max_concurrent_requests": 5 - }, - "passive_health_check": { - "max_failures": 5, - "interval": "4s" - } - } - } - } - `, - camelJSON: ` - { - "Kind": "service-defaults", - "Name": "main", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "Protocol": "http", - "ExternalSNI": "abc-123", - "MeshGateway": { - "Mode": "remote" - }, - "Mode": "direct", - "TransparentProxy": { - "OutboundListenerPort": 10101, - "DialedDirectly": true - }, - "UpstreamConfig": { - "Overrides": [ - { - "Name": "redis", - "PassiveHealthCheck": { - "MaxFailures": 3, - "Interval": "2s" - }, - "EnvoyListenerJson": "{ \"listener-foo\": 5 }", - "EnvoyClusterJson": "{ \"cluster-bar\": 5 }", - "Protocol": "grpc", - "ConnectTimeoutMs": 6543 - }, - { - "Name": "finance--billing", - "MeshGateway": { - "Mode": "remote" - }, - "Limits": { - "MaxConnections": 1111, - "MaxPendingRequests": 2222, - "MaxConcurrentRequests": 3333 - } - } - ], - "Defaults": { - "EnvoyClusterJson": "zip", - "EnvoyListenerJson": "zop", - "ConnectTimeoutMs": 5000, - "Protocol": "http", - "Limits": { - "MaxConnections": 3, - "MaxPendingRequests": 4, - "MaxConcurrentRequests": 5 - }, - "PassiveHealthCheck": { - "MaxFailures": 5, - "Interval": "4s" - } - } - } - } - `, - expect: &api.ServiceConfigEntry{ - Kind: "service-defaults", - Name: "main", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Protocol: "http", - ExternalSNI: "abc-123", - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeRemote, - }, - Mode: api.ProxyModeDirect, - TransparentProxy: &api.TransparentProxyConfig{ - OutboundListenerPort: 10101, - DialedDirectly: true, - }, - UpstreamConfig: &api.UpstreamConfiguration{ - Overrides: []*api.UpstreamConfig{ - { - Name: "redis", - PassiveHealthCheck: &api.PassiveHealthCheck{ - MaxFailures: 3, - Interval: 2 * time.Second, - }, - EnvoyListenerJSON: `{ "listener-foo": 5 }`, - EnvoyClusterJSON: `{ "cluster-bar": 5 }`, - Protocol: "grpc", - ConnectTimeoutMs: 6543, - }, - { - Name: "finance--billing", - MeshGateway: api.MeshGatewayConfig{ - Mode: "remote", - }, - Limits: &api.UpstreamLimits{ - MaxConnections: intPointer(1111), - MaxPendingRequests: intPointer(2222), - MaxConcurrentRequests: intPointer(3333), - }, - }, - }, - Defaults: &api.UpstreamConfig{ - EnvoyClusterJSON: "zip", - EnvoyListenerJSON: "zop", - Protocol: "http", - ConnectTimeoutMs: 5000, - Limits: &api.UpstreamLimits{ - MaxConnections: intPointer(3), - MaxPendingRequests: intPointer(4), - MaxConcurrentRequests: intPointer(5), - }, - PassiveHealthCheck: &api.PassiveHealthCheck{ - MaxFailures: 5, - Interval: 4 * time.Second, - }, - }, - }, - }, - }, - { - name: "service-defaults: kitchen sink (destination edition)", - snake: ` - kind = "service-defaults" - name = "main" - meta { - "foo" = "bar" - "gir" = "zim" - } - protocol = "grpc" - mesh_gateway { - mode = "remote" - } - mode = "transparent" - transparent_proxy = { - outbound_listener_port = 10101 - dialed_directly = true - } - destination = { - address = "10.0.0.0/16", - port = 443 - } - `, - camel: ` - Kind = "service-defaults" - Name = "main" - Meta { - "foo" = "bar" - "gir" = "zim" - } - Protocol = "grpc" - MeshGateway { - Mode = "remote" - } - Mode = "transparent" - TransparentProxy = { - outbound_listener_port = 10101 - dialed_directly = true - } - Destination = { - Address = "10.0.0.0/16", - Port = 443 - } - `, - snakeJSON: ` - { - "kind": "service-defaults", - "name": "main", - "meta" : { - "foo": "bar", - "gir": "zim" - }, - "protocol": "grpc", - "mesh_gateway": { - "mode": "remote" - }, - "mode": "transparent", - "transparent_proxy": { - "outbound_listener_port": 10101, - "dialed_directly": true - }, - "destination": { - "address": "10.0.0.0/16", - "port": 443 - } - } - `, - camelJSON: ` - { - "Kind": "service-defaults", - "Name": "main", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "Protocol": "grpc", - "MeshGateway": { - "Mode": "remote" - }, - "Mode": "transparent", - "TransparentProxy": { - "OutboundListenerPort": 10101, - "DialedDirectly": true - }, - "Destination": { - "Address": "10.0.0.0/16", - "Port": 443 - } - } - `, - expect: &api.ServiceConfigEntry{ - Kind: "service-defaults", - Name: "main", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Protocol: "grpc", - MeshGateway: api.MeshGatewayConfig{ - Mode: api.MeshGatewayModeRemote, - }, - Mode: api.ProxyModeTransparent, - TransparentProxy: &api.TransparentProxyConfig{ - OutboundListenerPort: 10101, - DialedDirectly: true, - }, - Destination: &api.DestinationConfig{ - Address: "10.0.0.0/16", - Port: 443, - }, - }, - }, - { - name: "service-router: kitchen sink", - snake: ` - kind = "service-router" - name = "main" - partition = "pepper" - meta { - "foo" = "bar" - "gir" = "zim" - } - routes = [ - { - match { - http { - path_exact = "/foo" - header = [ - { - name = "debug1" - present = true - }, - { - name = "debug2" - present = false - invert = true - }, - { - name = "debug3" - exact = "1" - }, - { - name = "debug4" - prefix = "aaa" - }, - { - name = "debug5" - suffix = "bbb" - }, - { - name = "debug6" - regex = "a.*z" - }, - ] - } - } - destination { - service = "carrot" - service_subset = "kale" - namespace = "leek" - partition = "chard" - prefix_rewrite = "/alternate" - request_timeout = "99s" - num_retries = 12345 - retry_on_connect_failure = true - retry_on_status_codes = [401, 209] - } - }, - { - match { - http { - path_prefix = "/foo" - methods = [ "GET", "DELETE" ] - query_param = [ - { - name = "hack1" - present = true - }, - { - name = "hack2" - exact = "1" - }, - { - name = "hack3" - regex = "a.*z" - }, - ] - } - } - }, - { - match { - http { - path_regex = "/foo" - } - } - }, - ] - `, - camel: ` - Kind = "service-router" - Name = "main" - Partition = "pepper" - Meta { - "foo" = "bar" - "gir" = "zim" - } - Routes = [ - { - Match { - HTTP { - PathExact = "/foo" - Header = [ - { - Name = "debug1" - Present = true - }, - { - Name = "debug2" - Present = false - Invert = true - }, - { - Name = "debug3" - Exact = "1" - }, - { - Name = "debug4" - Prefix = "aaa" - }, - { - Name = "debug5" - Suffix = "bbb" - }, - { - Name = "debug6" - Regex = "a.*z" - }, - ] - } - } - Destination { - Service = "carrot" - ServiceSubset = "kale" - Namespace = "leek" - Partition = "chard" - PrefixRewrite = "/alternate" - RequestTimeout = "99s" - NumRetries = 12345 - RetryOnConnectFailure = true - RetryOnStatusCodes = [401, 209] - } - }, - { - Match { - HTTP { - PathPrefix = "/foo" - Methods = [ "GET", "DELETE" ] - QueryParam = [ - { - Name = "hack1" - Present = true - }, - { - Name = "hack2" - Exact = "1" - }, - { - Name = "hack3" - Regex = "a.*z" - }, - ] - } - } - }, - { - Match { - HTTP { - PathRegex = "/foo" - } - } - }, - ] - `, - snakeJSON: ` - { - "kind": "service-router", - "name": "main", - "partition": "pepper", - "meta" : { - "foo": "bar", - "gir": "zim" - }, - "routes": [ - { - "match": { - "http": { - "path_exact": "/foo", - "header": [ - { - "name": "debug1", - "present": true - }, - { - "name": "debug2", - "present": false, - "invert": true - }, - { - "name": "debug3", - "exact": "1" - }, - { - "name": "debug4", - "prefix": "aaa" - }, - { - "name": "debug5", - "suffix": "bbb" - }, - { - "name": "debug6", - "regex": "a.*z" - } - ] - } - }, - "destination": { - "service": "carrot", - "service_subset": "kale", - "namespace": "leek", - "partition": "chard", - "prefix_rewrite": "/alternate", - "request_timeout": "99s", - "num_retries": 12345, - "retry_on_connect_failure": true, - "retry_on_status_codes": [ - 401, - 209 - ] - } - }, - { - "match": { - "http": { - "path_prefix": "/foo", - "methods": [ - "GET", - "DELETE" - ], - "query_param": [ - { - "name": "hack1", - "present": true - }, - { - "name": "hack2", - "exact": "1" - }, - { - "name": "hack3", - "regex": "a.*z" - } - ] - } - } - }, - { - "match": { - "http": { - "path_regex": "/foo" - } - } - } - ] - } - `, - camelJSON: ` - { - "Kind": "service-router", - "Name": "main", - "Partition": "pepper", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "Routes": [ - { - "Match": { - "HTTP": { - "PathExact": "/foo", - "Header": [ - { - "Name": "debug1", - "Present": true - }, - { - "Name": "debug2", - "Present": false, - "Invert": true - }, - { - "Name": "debug3", - "Exact": "1" - }, - { - "Name": "debug4", - "Prefix": "aaa" - }, - { - "Name": "debug5", - "Suffix": "bbb" - }, - { - "Name": "debug6", - "Regex": "a.*z" - } - ] - } - }, - "Destination": { - "Service": "carrot", - "ServiceSubset": "kale", - "Namespace": "leek", - "Partition": "chard", - "PrefixRewrite": "/alternate", - "RequestTimeout": "99s", - "NumRetries": 12345, - "RetryOnConnectFailure": true, - "RetryOnStatusCodes": [ - 401, - 209 - ] - } - }, - { - "Match": { - "HTTP": { - "PathPrefix": "/foo", - "Methods": [ - "GET", - "DELETE" - ], - "QueryParam": [ - { - "Name": "hack1", - "Present": true - }, - { - "Name": "hack2", - "Exact": "1" - }, - { - "Name": "hack3", - "Regex": "a.*z" - } - ] - } - } - }, - { - "Match": { - "HTTP": { - "PathRegex": "/foo" - } - } - } - ] - } - `, - expect: &api.ServiceRouterConfigEntry{ - Kind: "service-router", - Name: "main", - Partition: "pepper", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Routes: []api.ServiceRoute{ - { - Match: &api.ServiceRouteMatch{ - HTTP: &api.ServiceRouteHTTPMatch{ - PathExact: "/foo", - Header: []api.ServiceRouteHTTPMatchHeader{ - { - Name: "debug1", - Present: true, - }, - { - Name: "debug2", - Present: false, - Invert: true, - }, - { - Name: "debug3", - Exact: "1", - }, - { - Name: "debug4", - Prefix: "aaa", - }, - { - Name: "debug5", - Suffix: "bbb", - }, - { - Name: "debug6", - Regex: "a.*z", - }, - }, - }, - }, - Destination: &api.ServiceRouteDestination{ - Service: "carrot", - ServiceSubset: "kale", - Namespace: "leek", - Partition: "chard", - PrefixRewrite: "/alternate", - RequestTimeout: 99 * time.Second, - NumRetries: 12345, - RetryOnConnectFailure: true, - RetryOnStatusCodes: []uint32{401, 209}, - }, - }, - { - Match: &api.ServiceRouteMatch{ - HTTP: &api.ServiceRouteHTTPMatch{ - PathPrefix: "/foo", - Methods: []string{"GET", "DELETE"}, - QueryParam: []api.ServiceRouteHTTPMatchQueryParam{ - { - Name: "hack1", - Present: true, - }, - { - Name: "hack2", - Exact: "1", - }, - { - Name: "hack3", - Regex: "a.*z", - }, - }, - }, - }, - }, - { - Match: &api.ServiceRouteMatch{ - HTTP: &api.ServiceRouteHTTPMatch{ - PathRegex: "/foo", - }, - }, - }, - }, - }, - }, - { - name: "service-splitter: kitchen sink", - snake: ` - kind = "service-splitter" - name = "main" - partition = "east" - meta { - "foo" = "bar" - "gir" = "zim" - } - splits = [ - { - weight = 97.1 - service_subset = "v1" - }, - { - weight = 2 - service_subset = "v2" - }, - { - weight = 0.9 - service = "other" - namespace = "alt" - partition = "west" - }, - ] - `, - camel: ` - Kind = "service-splitter" - Name = "main" - Partition = "east" - Meta { - "foo" = "bar" - "gir" = "zim" - } - Splits = [ - { - Weight = 97.1 - ServiceSubset = "v1" - }, - { - Weight = 2, - ServiceSubset = "v2" - }, - { - Weight = 0.9 - Service = "other" - Namespace = "alt" - Partition = "west" - }, - ] - `, - snakeJSON: ` - { - "kind": "service-splitter", - "name": "main", - "partition": "east", - "meta" : { - "foo": "bar", - "gir": "zim" - }, - "splits": [ - { - "weight": 97.1, - "service_subset": "v1" - }, - { - "weight": 2, - "service_subset": "v2" - }, - { - "weight": 0.9, - "service": "other", - "namespace": "alt", - "partition": "west" - } - ] - } - `, - camelJSON: ` - { - "Kind": "service-splitter", - "Name": "main", - "Partition": "east", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "Splits": [ - { - "Weight": 97.1, - "ServiceSubset": "v1" - }, - { - "Weight": 2, - "ServiceSubset": "v2" - }, - { - "Weight": 0.9, - "Service": "other", - "Namespace": "alt", - "Partition": "west" - } - ] - } - `, - expect: &api.ServiceSplitterConfigEntry{ - Kind: api.ServiceSplitter, - Name: "main", - Partition: "east", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Splits: []api.ServiceSplit{ - { - Weight: 97.1, - ServiceSubset: "v1", - }, - { - Weight: 2, - ServiceSubset: "v2", - }, - { - Weight: 0.9, - Service: "other", - Namespace: "alt", - Partition: "west", - }, - }, - }, - }, - { - name: "service-resolver: subsets with failover", - snake: ` - kind = "service-resolver" - name = "main" - meta { - "foo" = "bar" - "gir" = "zim" - } - default_subset = "v1" - connect_timeout = "15s" - subsets = { - "v1" = { - filter = "Service.Meta.version == v1" - }, - "v2" = { - filter = "Service.Meta.version == v2" - only_passing = true - }, - } - failover = { - "v2" = { - service = "failcopy" - service_subset = "sure" - namespace = "neighbor" - datacenters = ["dc5", "dc14"] - }, - "*" = { - datacenters = ["dc7"] - } - }`, - camel: ` - Kind = "service-resolver" - Name = "main" - Meta { - "foo" = "bar" - "gir" = "zim" - } - DefaultSubset = "v1" - ConnectTimeout = "15s" - Subsets = { - "v1" = { - Filter = "Service.Meta.version == v1" - }, - "v2" = { - Filter = "Service.Meta.version == v2" - OnlyPassing = true - }, - } - Failover = { - "v2" = { - Service = "failcopy" - ServiceSubset = "sure" - Namespace = "neighbor" - Datacenters = ["dc5", "dc14"] - }, - "*" = { - Datacenters = ["dc7"] - } - }`, - snakeJSON: ` - { - "kind": "service-resolver", - "name": "main", - "meta" : { - "foo": "bar", - "gir": "zim" - }, - "default_subset": "v1", - "connect_timeout": "15s", - "subsets": { - "v1": { - "filter": "Service.Meta.version == v1" - }, - "v2": { - "filter": "Service.Meta.version == v2", - "only_passing": true - } - }, - "failover": { - "v2": { - "service": "failcopy", - "service_subset": "sure", - "namespace": "neighbor", - "datacenters": [ - "dc5", - "dc14" - ] - }, - "*": { - "datacenters": [ - "dc7" - ] - } - } - } - `, - camelJSON: ` - { - "Kind": "service-resolver", - "Name": "main", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "DefaultSubset": "v1", - "ConnectTimeout": "15s", - "Subsets": { - "v1": { - "Filter": "Service.Meta.version == v1" - }, - "v2": { - "Filter": "Service.Meta.version == v2", - "OnlyPassing": true - } - }, - "Failover": { - "v2": { - "Service": "failcopy", - "ServiceSubset": "sure", - "Namespace": "neighbor", - "Datacenters": [ - "dc5", - "dc14" - ] - }, - "*": { - "Datacenters": [ - "dc7" - ] - } - } - } - `, - expect: &api.ServiceResolverConfigEntry{ - Kind: "service-resolver", - Name: "main", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - DefaultSubset: "v1", - ConnectTimeout: 15 * time.Second, - Subsets: map[string]api.ServiceResolverSubset{ - "v1": { - Filter: "Service.Meta.version == v1", - }, - "v2": { - Filter: "Service.Meta.version == v2", - OnlyPassing: true, - }, - }, - Failover: map[string]api.ServiceResolverFailover{ - "v2": { - Service: "failcopy", - ServiceSubset: "sure", - Namespace: "neighbor", - Datacenters: []string{"dc5", "dc14"}, - }, - "*": { - Datacenters: []string{"dc7"}, - }, - }, - }, - }, - { - name: "service-resolver: redirect", - snake: ` - kind = "service-resolver" - name = "main" - partition = "east" - redirect { - service = "other" - service_subset = "backup" - namespace = "alt" - partition = "west" - datacenter = "dc9" - } - `, - camel: ` - Kind = "service-resolver" - Name = "main" - Partition = "east" - Redirect { - Service = "other" - ServiceSubset = "backup" - Namespace = "alt" - Partition = "west" - Datacenter = "dc9" - } - `, - snakeJSON: ` - { - "kind": "service-resolver", - "name": "main", - "partition": "east", - "redirect": { - "service": "other", - "service_subset": "backup", - "namespace": "alt", - "partition": "west", - "datacenter": "dc9" - } - } - `, - camelJSON: ` - { - "Kind": "service-resolver", - "Name": "main", - "Partition": "east", - "Redirect": { - "Service": "other", - "ServiceSubset": "backup", - "Namespace": "alt", - "Partition": "west", - "Datacenter": "dc9" - } - } - `, - expect: &api.ServiceResolverConfigEntry{ - Kind: "service-resolver", - Name: "main", - Partition: "east", - Redirect: &api.ServiceResolverRedirect{ - Service: "other", - ServiceSubset: "backup", - Namespace: "alt", - Partition: "west", - Datacenter: "dc9", - }, - }, - }, - { - name: "service-resolver: default", - snake: ` - kind = "service-resolver" - name = "main" - `, - camel: ` - Kind = "service-resolver" - Name = "main" - `, - snakeJSON: ` - { - "kind": "service-resolver", - "name": "main" - } - `, - camelJSON: ` - { - "Kind": "service-resolver", - "Name": "main" - } - `, - expect: &api.ServiceResolverConfigEntry{ - Kind: "service-resolver", - Name: "main", - }, - }, - { - name: "service-resolver: envoy hash lb kitchen sink", - snake: ` - kind = "service-resolver" - name = "main" - load_balancer = { - policy = "ring_hash" - ring_hash_config = { - minimum_ring_size = 1 - maximum_ring_size = 2 - } - hash_policies = [ - { - field = "cookie" - field_value = "good-cookie" - cookie_config = { - ttl = "1s" - path = "/oven" - } - terminal = true - }, - { - field = "cookie" - field_value = "less-good-cookie" - cookie_config = { - session = true - path = "/toaster" - } - terminal = true - }, - { - field = "header" - field_value = "x-user-id" - }, - { - source_ip = true - } - ] - } - `, - camel: ` - Kind = "service-resolver" - Name = "main" - LoadBalancer = { - Policy = "ring_hash" - RingHashConfig = { - MinimumRingSize = 1 - MaximumRingSize = 2 - } - HashPolicies = [ - { - Field = "cookie" - FieldValue = "good-cookie" - CookieConfig = { - TTL = "1s" - Path = "/oven" - } - Terminal = true - }, - { - Field = "cookie" - FieldValue = "less-good-cookie" - CookieConfig = { - Session = true - Path = "/toaster" - } - Terminal = true - }, - { - Field = "header" - FieldValue = "x-user-id" - }, - { - SourceIP = true - } - ] - } - `, - snakeJSON: ` - { - "kind": "service-resolver", - "name": "main", - "load_balancer": { - "policy": "ring_hash", - "ring_hash_config": { - "minimum_ring_size": 1, - "maximum_ring_size": 2 - }, - "hash_policies": [ - { - "field": "cookie", - "field_value": "good-cookie", - "cookie_config": { - "ttl": "1s", - "path": "/oven" - }, - "terminal": true - }, - { - "field": "cookie", - "field_value": "less-good-cookie", - "cookie_config": { - "session": true, - "path": "/toaster" - }, - "terminal": true - }, - { - "field": "header", - "field_value": "x-user-id" - }, - { - "source_ip": true - } - ] - } - } - `, - camelJSON: ` - { - "Kind": "service-resolver", - "Name": "main", - "LoadBalancer": { - "Policy": "ring_hash", - "RingHashConfig": { - "MinimumRingSize": 1, - "MaximumRingSize": 2 - }, - "HashPolicies": [ - { - "Field": "cookie", - "FieldValue": "good-cookie", - "CookieConfig": { - "TTL": "1s", - "Path": "/oven" - }, - "Terminal": true - }, - { - "Field": "cookie", - "FieldValue": "less-good-cookie", - "CookieConfig": { - "Session": true, - "Path": "/toaster" - }, - "Terminal": true - }, - { - "Field": "header", - "FieldValue": "x-user-id" - }, - { - "SourceIP": true - } - ] - } - } - `, - expect: &api.ServiceResolverConfigEntry{ - Kind: "service-resolver", - Name: "main", - LoadBalancer: &api.LoadBalancer{ - Policy: structs.LBPolicyRingHash, - RingHashConfig: &api.RingHashConfig{ - MinimumRingSize: 1, - MaximumRingSize: 2, - }, - HashPolicies: []api.HashPolicy{ - { - Field: structs.HashPolicyCookie, - FieldValue: "good-cookie", - CookieConfig: &api.CookieConfig{ - TTL: 1 * time.Second, - Path: "/oven", - }, - Terminal: true, - }, - { - Field: structs.HashPolicyCookie, - FieldValue: "less-good-cookie", - CookieConfig: &api.CookieConfig{ - Session: true, - Path: "/toaster", - }, - Terminal: true, - }, - { - Field: structs.HashPolicyHeader, - FieldValue: "x-user-id", - }, - { - SourceIP: true, - }, - }, - }, - }, - }, - { - name: "service-resolver: envoy least request kitchen sink", - snake: ` - kind = "service-resolver" - name = "main" - load_balancer = { - policy = "least_request" - least_request_config = { - choice_count = 2 - } - } - `, - camel: ` - Kind = "service-resolver" - Name = "main" - LoadBalancer = { - Policy = "least_request" - LeastRequestConfig = { - ChoiceCount = 2 - } - } - `, - snakeJSON: ` - { - "kind": "service-resolver", - "name": "main", - "load_balancer": { - "policy": "least_request", - "least_request_config": { - "choice_count": 2 - } - } - } - `, - camelJSON: ` - { - "Kind": "service-resolver", - "Name": "main", - "LoadBalancer": { - "Policy": "least_request", - "LeastRequestConfig": { - "ChoiceCount": 2 - } - } - } - `, - expect: &api.ServiceResolverConfigEntry{ - Kind: "service-resolver", - Name: "main", - LoadBalancer: &api.LoadBalancer{ - Policy: structs.LBPolicyLeastRequest, - LeastRequestConfig: &api.LeastRequestConfig{ - ChoiceCount: 2, - }, - }, - }, - }, - { - name: "expose paths: kitchen sink proxy defaults", - snake: ` - kind = "proxy-defaults" - name = "global" - expose = { - checks = true - paths = [ - { - local_path_port = 8080 - listener_port = 21500 - path = "/healthz" - protocol = "http2" - }, - { - local_path_port = 8000 - listener_port = 21501 - path = "/metrics" - protocol = "http" - } - ] - }`, - camel: ` - Kind = "proxy-defaults" - Name = "global" - Expose = { - Checks = true - Paths = [ - { - LocalPathPort = 8080 - ListenerPort = 21500 - Path = "/healthz" - Protocol = "http2" - }, - { - LocalPathPort = 8000 - ListenerPort = 21501 - Path = "/metrics" - Protocol = "http" - } - ] - }`, - snakeJSON: ` - { - "kind": "proxy-defaults", - "name": "global", - "expose": { - "checks": true, - "paths": [ - { - "local_path_port": 8080, - "listener_port": 21500, - "path": "/healthz", - "protocol": "http2" - }, - { - "local_path_port": 8000, - "listener_port": 21501, - "path": "/metrics", - "protocol": "http" - } - ] - } - } - `, - camelJSON: ` - { - "Kind": "proxy-defaults", - "Name": "global", - "Expose": { - "Checks": true, - "Paths": [ - { - "LocalPathPort": 8080, - "ListenerPort": 21500, - "Path": "/healthz", - "Protocol": "http2" - }, - { - "LocalPathPort": 8000, - "ListenerPort": 21501, - "Path": "/metrics", - "Protocol": "http" - } - ] - } - } - `, - expect: &api.ProxyConfigEntry{ - Kind: "proxy-defaults", - Name: "global", - Expose: api.ExposeConfig{ - Checks: true, - Paths: []api.ExposePath{ - { - ListenerPort: 21500, - Path: "/healthz", - LocalPathPort: 8080, - Protocol: "http2", - }, - { - ListenerPort: 21501, - Path: "/metrics", - LocalPathPort: 8000, - Protocol: "http", - }, - }, - }, - }, - }, - { - name: "expose paths: kitchen sink service defaults", - snake: ` - kind = "service-defaults" - name = "web" - expose = { - checks = true - paths = [ - { - local_path_port = 8080 - listener_port = 21500 - path = "/healthz" - protocol = "http2" - }, - { - local_path_port = 8000 - listener_port = 21501 - path = "/metrics" - protocol = "http" - } - ] - }`, - camel: ` - Kind = "service-defaults" - Name = "web" - Expose = { - Checks = true - Paths = [ - { - LocalPathPort = 8080 - ListenerPort = 21500 - Path = "/healthz" - Protocol = "http2" - }, - { - LocalPathPort = 8000 - ListenerPort = 21501 - Path = "/metrics" - Protocol = "http" - } - ] - }`, - snakeJSON: ` - { - "kind": "service-defaults", - "name": "web", - "expose": { - "checks": true, - "paths": [ - { - "local_path_port": 8080, - "listener_port": 21500, - "path": "/healthz", - "protocol": "http2" - }, - { - "local_path_port": 8000, - "listener_port": 21501, - "path": "/metrics", - "protocol": "http" - } - ] - } - } - `, - camelJSON: ` - { - "Kind": "service-defaults", - "Name": "web", - "Expose": { - "Checks": true, - "Paths": [ - { - "LocalPathPort": 8080, - "ListenerPort": 21500, - "Path": "/healthz", - "Protocol": "http2" - }, - { - "LocalPathPort": 8000, - "ListenerPort": 21501, - "Path": "/metrics", - "Protocol": "http" - } - ] - } - } - `, - expect: &api.ServiceConfigEntry{ - Kind: "service-defaults", - Name: "web", - Expose: api.ExposeConfig{ - Checks: true, - Paths: []api.ExposePath{ - { - ListenerPort: 21500, - Path: "/healthz", - LocalPathPort: 8080, - Protocol: "http2", - }, - { - ListenerPort: 21501, - Path: "/metrics", - LocalPathPort: 8000, - Protocol: "http", - }, - }, - }, - }, - }, - { - // TODO(rb): test SDS stuff here in both places (global/service) - name: "ingress-gateway: kitchen sink", - snake: ` - kind = "ingress-gateway" - name = "ingress-web" - meta { - "foo" = "bar" - "gir" = "zim" - } - tls { - enabled = true - tls_min_version = "TLSv1_1" - tls_max_version = "TLSv1_2" - cipher_suites = [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - } - listeners = [ - { - port = 8080 - protocol = "http" - services = [ - { - name = "web" - hosts = ["test.example.com"] - }, - { - name = "db" - namespace = "foo" - } - ] - } - ] - `, - camel: ` - Kind = "ingress-gateway" - Name = "ingress-web" - Meta { - "foo" = "bar" - "gir" = "zim" - } - Tls { - Enabled = true - TLSMinVersion = "TLSv1_1" - TLSMaxVersion = "TLSv1_2" - CipherSuites = [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - } - Listeners = [ - { - Port = 8080 - Protocol = "http" - Services = [ - { - Name = "web" - Hosts = ["test.example.com"] - }, - { - Name = "db" - Namespace = "foo" - } - ] - } - ] - `, - snakeJSON: ` - { - "kind": "ingress-gateway", - "name": "ingress-web", - "meta" : { - "foo": "bar", - "gir": "zim" - }, - "tls": { - "enabled": true, - "tls_min_version": "TLSv1_1", - "tls_max_version": "TLSv1_2", - "cipher_suites": [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - }, - "listeners": [ - { - "port": 8080, - "protocol": "http", - "services": [ - { - "name": "web", - "hosts": ["test.example.com"] - }, - { - "name": "db", - "namespace": "foo" - } - ] - } - ] - } - `, - camelJSON: ` - { - "Kind": "ingress-gateway", - "Name": "ingress-web", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "TLS": { - "Enabled": true, - "TLSMinVersion": "TLSv1_1", - "TLSMaxVersion": "TLSv1_2", - "CipherSuites": [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - }, - "Listeners": [ - { - "Port": 8080, - "Protocol": "http", - "Services": [ - { - "Name": "web", - "Hosts": ["test.example.com"] - }, - { - "Name": "db", - "Namespace": "foo" - } - ] - } - ] - } - `, - expect: &api.IngressGatewayConfigEntry{ - Kind: "ingress-gateway", - Name: "ingress-web", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - TLS: api.GatewayTLSConfig{ - Enabled: true, - TLSMinVersion: "TLSv1_1", - TLSMaxVersion: "TLSv1_2", - CipherSuites: []string{ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - }, - }, - Listeners: []api.IngressListener{ - { - Port: 8080, - Protocol: "http", - Services: []api.IngressService{ - { - Name: "web", - Hosts: []string{"test.example.com"}, - }, - { - Name: "db", - Namespace: "foo", - }, - }, - }, - }, - }, - }, - { - name: "service-intentions: kitchen sink", - snake: ` - kind = "service-intentions" - name = "web" - meta { - "foo" = "bar" - "gir" = "zim" - } - sources = [ - { - name = "foo" - action = "deny" - type = "consul" - description = "foo desc" - }, - { - name = "bar" - action = "allow" - description = "bar desc" - }, - { - name = "l7" - permissions = [ - { - action = "deny" - http { - path_exact = "/admin" - header = [ - { - name = "hdr-present" - present = true - }, - { - name = "hdr-exact" - exact = "exact" - }, - { - name = "hdr-prefix" - prefix = "prefix" - }, - { - name = "hdr-suffix" - suffix = "suffix" - }, - { - name = "hdr-regex" - regex = "regex" - }, - { - name = "hdr-absent" - present = true - invert = true - } - ] - } - }, - { - action = "allow" - http { - path_prefix = "/v3/" - } - }, - { - action = "allow" - http { - path_regex = "/v[12]/.*" - methods = ["GET", "POST"] - } - } - ] - } - ] - sources { - name = "*" - action = "deny" - description = "wild desc" - } - `, - camel: ` - Kind = "service-intentions" - Name = "web" - Meta { - "foo" = "bar" - "gir" = "zim" - } - Sources = [ - { - Name = "foo" - Action = "deny" - Type = "consul" - Description = "foo desc" - }, - { - Name = "bar" - Action = "allow" - Description = "bar desc" - }, - { - Name = "l7" - Permissions = [ - { - Action = "deny" - HTTP { - PathExact = "/admin" - Header = [ - { - Name = "hdr-present" - Present = true - }, - { - Name = "hdr-exact" - Exact = "exact" - }, - { - Name = "hdr-prefix" - Prefix = "prefix" - }, - { - Name = "hdr-suffix" - Suffix = "suffix" - }, - { - Name = "hdr-regex" - Regex = "regex" - }, - { - Name = "hdr-absent" - Present = true - Invert = true - } - ] - } - }, - { - Action = "allow" - HTTP { - PathPrefix = "/v3/" - } - }, - { - Action = "allow" - HTTP { - PathRegex = "/v[12]/.*" - Methods = ["GET", "POST"] - } - } - ] - } - ] - Sources { - Name = "*" - Action = "deny" - Description = "wild desc" - } - `, - snakeJSON: ` - { - "kind": "service-intentions", - "name": "web", - "meta": { - "foo": "bar", - "gir": "zim" - }, - "sources": [ - { - "name": "foo", - "action": "deny", - "type": "consul", - "description": "foo desc" - }, - { - "name": "bar", - "action": "allow", - "description": "bar desc" - }, - { - "name": "l7", - "permissions": [ - { - "action": "deny", - "http": { - "path_exact": "/admin", - "header": [ - { - "name": "hdr-present", - "present": true - }, - { - "name": "hdr-exact", - "exact": "exact" - }, - { - "name": "hdr-prefix", - "prefix": "prefix" - }, - { - "name": "hdr-suffix", - "suffix": "suffix" - }, - { - "name": "hdr-regex", - "regex": "regex" - }, - { - "name": "hdr-absent", - "present": true, - "invert": true - } - ] - } - }, - { - "action": "allow", - "http": { - "path_prefix": "/v3/" - } - }, - { - "action": "allow", - "http": { - "path_regex": "/v[12]/.*", - "methods": [ - "GET", - "POST" - ] - } - } - ] - }, - { - "name": "*", - "action": "deny", - "description": "wild desc" - } - ] - } - `, - camelJSON: ` - { - "Kind": "service-intentions", - "Name": "web", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "Sources": [ - { - "Name": "foo", - "Action": "deny", - "Type": "consul", - "Description": "foo desc" - }, - { - "Name": "bar", - "Action": "allow", - "Description": "bar desc" - }, - { - "Name": "l7", - "Permissions": [ - { - "Action": "deny", - "HTTP": { - "PathExact": "/admin", - "Header": [ - { - "Name": "hdr-present", - "Present": true - }, - { - "Name": "hdr-exact", - "Exact": "exact" - }, - { - "Name": "hdr-prefix", - "Prefix": "prefix" - }, - { - "Name": "hdr-suffix", - "Suffix": "suffix" - }, - { - "Name": "hdr-regex", - "Regex": "regex" - }, - { - "Name": "hdr-absent", - "Present": true, - "Invert": true - } - ] - } - }, - { - "Action": "allow", - "HTTP": { - "PathPrefix": "/v3/" - } - }, - { - "Action": "allow", - "HTTP": { - "PathRegex": "/v[12]/.*", - "Methods": [ - "GET", - "POST" - ] - } - } - ] - }, - { - "Name": "*", - "Action": "deny", - "Description": "wild desc" - } - ] - } - `, - expect: &api.ServiceIntentionsConfigEntry{ - Kind: "service-intentions", - Name: "web", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Sources: []*api.SourceIntention{ - { - Name: "foo", - Action: "deny", - Type: "consul", - Description: "foo desc", - }, - { - Name: "bar", - Action: "allow", - Description: "bar desc", - }, - { - Name: "l7", - Permissions: []*api.IntentionPermission{ - { - Action: "deny", - HTTP: &api.IntentionHTTPPermission{ - PathExact: "/admin", - Header: []api.IntentionHTTPHeaderPermission{ - { - Name: "hdr-present", - Present: true, - }, - { - Name: "hdr-exact", - Exact: "exact", - }, - { - Name: "hdr-prefix", - Prefix: "prefix", - }, - { - Name: "hdr-suffix", - Suffix: "suffix", - }, - { - Name: "hdr-regex", - Regex: "regex", - }, - { - Name: "hdr-absent", - Present: true, - Invert: true, - }, - }, - }, - }, - { - Action: "allow", - HTTP: &api.IntentionHTTPPermission{ - PathPrefix: "/v3/", - }, - }, - { - Action: "allow", - HTTP: &api.IntentionHTTPPermission{ - PathRegex: "/v[12]/.*", - Methods: []string{"GET", "POST"}, - }, - }, - }, - }, - { - Name: "*", - Action: "deny", - Description: "wild desc", - }, - }, - }, - }, - { - name: "service-intentions: wildcard destination", - snake: ` - kind = "service-intentions" - name = "*" - sources { - name = "foo" - action = "deny" - # should be parsed, but we'll ignore it later - precedence = 6 - } - `, - camel: ` - Kind = "service-intentions" - Name = "*" - Sources { - Name = "foo" - Action = "deny" - # should be parsed, but we'll ignore it later - Precedence = 6 - } - `, - snakeJSON: ` - { - "kind": "service-intentions", - "name": "*", - "sources": [ - { - "name": "foo", - "action": "deny", - "precedence": 6 - } - ] - } - `, - camelJSON: ` - { - "Kind": "service-intentions", - "Name": "*", - "Sources": [ - { - "Name": "foo", - "Action": "deny", - "Precedence": 6 - } - ] - } - `, - expect: &api.ServiceIntentionsConfigEntry{ - Kind: "service-intentions", - Name: "*", - Sources: []*api.SourceIntention{ - { - Name: "foo", - Action: "deny", - Precedence: 6, - }, - }, - }, - }, - { - name: "mesh", - snake: ` - kind = "mesh" - meta { - "foo" = "bar" - "gir" = "zim" - } - transparent_proxy { - mesh_destinations_only = true - } - tls { - incoming { - tls_min_version = "TLSv1_1" - tls_max_version = "TLSv1_2" - cipher_suites = [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - } - outgoing { - tls_min_version = "TLSv1_1" - tls_max_version = "TLSv1_2" - cipher_suites = [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - } - } - `, - camel: ` - Kind = "mesh" - Meta { - "foo" = "bar" - "gir" = "zim" - } - TransparentProxy { - MeshDestinationsOnly = true - } - TLS { - Incoming { - TLSMinVersion = "TLSv1_1" - TLSMaxVersion = "TLSv1_2" - CipherSuites = [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - } - Outgoing { - TLSMinVersion = "TLSv1_1" - TLSMaxVersion = "TLSv1_2" - CipherSuites = [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - } - } - `, - snakeJSON: ` - { - "kind": "mesh", - "meta" : { - "foo": "bar", - "gir": "zim" - }, - "transparent_proxy": { - "mesh_destinations_only": true - }, - "tls": { - "incoming": { - "tls_min_version": "TLSv1_1", - "tls_max_version": "TLSv1_2", - "cipher_suites": [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - }, - "outgoing": { - "tls_min_version": "TLSv1_1", - "tls_max_version": "TLSv1_2", - "cipher_suites": [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - } - } - } - `, - camelJSON: ` - { - "Kind": "mesh", - "Meta" : { - "foo": "bar", - "gir": "zim" - }, - "TransparentProxy": { - "MeshDestinationsOnly": true - }, - "TLS": { - "Incoming": { - "TLSMinVersion": "TLSv1_1", - "TLSMaxVersion": "TLSv1_2", - "CipherSuites": [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - }, - "Outgoing": { - "TLSMinVersion": "TLSv1_1", - "TLSMaxVersion": "TLSv1_2", - "CipherSuites": [ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" - ] - } - } - } - `, - expect: &api.MeshConfigEntry{ - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - TransparentProxy: api.TransparentProxyMeshConfig{ - MeshDestinationsOnly: true, - }, - TLS: &api.MeshTLSConfig{ - Incoming: &api.MeshDirectionalTLSConfig{ - TLSMinVersion: "TLSv1_1", - TLSMaxVersion: "TLSv1_2", - CipherSuites: []string{ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - }, - }, - Outgoing: &api.MeshDirectionalTLSConfig{ - TLSMinVersion: "TLSv1_1", - TLSMaxVersion: "TLSv1_2", - CipherSuites: []string{ - "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - }, - }, - }, - }, - }, - { - name: "exported-services", - snake: ` - kind = "exported-services" - name = "foo" - meta { - "foo" = "bar" - "gir" = "zim" - } - services = [ - { - name = "web" - namespace = "foo" - consumers = [ - { - partition = "bar" - }, - { - partition = "baz" - }, - { - peer_name = "flarm" - } - ] - }, - { - name = "db" - namespace = "bar" - consumers = [ - { - partition = "zoo" - } - ] - } - ] - `, - camel: ` - Kind = "exported-services" - Name = "foo" - Meta { - "foo" = "bar" - "gir" = "zim" - } - Services = [ - { - Name = "web" - Namespace = "foo" - Consumers = [ - { - Partition = "bar" - }, - { - Partition = "baz" - }, - { - PeerName = "flarm" - } - ] - }, - { - Name = "db" - Namespace = "bar" - Consumers = [ - { - Partition = "zoo" - } - ] - } - ] - `, - snakeJSON: ` - { - "kind": "exported-services", - "name": "foo", - "meta": { - "foo": "bar", - "gir": "zim" - }, - "services": [ - { - "name": "web", - "namespace": "foo", - "consumers": [ - { - "partition": "bar" - }, - { - "partition": "baz" - }, - { - "peer_name": "flarm" - } - ] - }, - { - "name": "db", - "namespace": "bar", - "consumers": [ - { - "partition": "zoo" - } - ] - } - ] - } - `, - camelJSON: ` - { - "Kind": "exported-services", - "Name": "foo", - "Meta": { - "foo": "bar", - "gir": "zim" - }, - "Services": [ - { - "Name": "web", - "Namespace": "foo", - "Consumers": [ - { - "Partition": "bar" - }, - { - "Partition": "baz" - }, - { - "PeerName": "flarm" - } - ] - }, - { - "Name": "db", - "Namespace": "bar", - "Consumers": [ - { - "Partition": "zoo" - } - ] - } - ] - } - `, - expect: &api.ExportedServicesConfigEntry{ - Name: "foo", - Meta: map[string]string{ - "foo": "bar", - "gir": "zim", - }, - Services: []api.ExportedService{ - { - Name: "web", - Namespace: "foo", - Consumers: []api.ServiceConsumer{ - { - Partition: "bar", - }, - { - Partition: "baz", - }, - { - PeerName: "flarm", - }, - }, - }, - { - Name: "db", - Namespace: "bar", - Consumers: []api.ServiceConsumer{ - { - Partition: "zoo", - }, - }, - }, - }, - }, - }, - } { - tc := tc - - testbody := func(t *testing.T, body string, expect api.ConfigEntry) { - t.Helper() - got, err := parseConfigEntry(body) - if tc.expectErr != "" { - require.Nil(t, got) - require.Error(t, err) - requireContainsLower(t, err.Error(), tc.expectErr) - } else { - require.NoError(t, err) - require.Equal(t, expect, got) - } - } - - t.Run(tc.name+" (hcl snake case)", func(t *testing.T) { - testbody(t, tc.snake, tc.expect) - }) - t.Run(tc.name+" (hcl camel case)", func(t *testing.T) { - testbody(t, tc.camel, tc.expect) - }) - if tc.snakeJSON != "" { - t.Run(tc.name+" (json snake case)", func(t *testing.T) { - if tc.expectJSON != nil { - testbody(t, tc.snakeJSON, tc.expectJSON) - } else { - testbody(t, tc.snakeJSON, tc.expect) - } - }) - } - if tc.camelJSON != "" { - t.Run(tc.name+" (json camel case)", func(t *testing.T) { - if tc.expectJSON != nil { - testbody(t, tc.camelJSON, tc.expectJSON) - } else { - testbody(t, tc.camelJSON, tc.expect) - } - }) - } - } -} - func requireContainsLower(t *testing.T, haystack, needle string) { t.Helper() require.Contains(t, strings.ToLower(haystack), strings.ToLower(needle)) } - -func intPointer(v int) *int { - return &v -} diff --git a/command/connect/envoy/bootstrap_config.go b/command/connect/envoy/bootstrap_config.go index f2ea33b7f2..d101d19e4e 100644 --- a/command/connect/envoy/bootstrap_config.go +++ b/command/connect/envoy/bootstrap_config.go @@ -653,9 +653,7 @@ func (c *BootstrapConfig) generateListenerConfig(args *BootstrapTplArgs, bindAdd } ], "validationContextSdsSecretConfig": { - "trustedCa": { - "name": "prometheus_validation_context" - } + "name": "prometheus_validation_context" } } } diff --git a/command/connect/envoy/bootstrap_config_test.go b/command/connect/envoy/bootstrap_config_test.go index bb471566c3..1e928db173 100644 --- a/command/connect/envoy/bootstrap_config_test.go +++ b/command/connect/envoy/bootstrap_config_test.go @@ -342,9 +342,7 @@ const ( } ], "validationContextSdsSecretConfig": { - "trustedCa": { - "name": "prometheus_validation_context" - } + "name": "prometheus_validation_context" } } } diff --git a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden index 64d0951b2f..2f508b1e23 100644 --- a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden +++ b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-file.golden @@ -151,9 +151,7 @@ } ], "validationContextSdsSecretConfig": { - "trustedCa": { - "name": "prometheus_validation_context" - } + "name": "prometheus_validation_context" } } } diff --git a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden index 34cbbda972..e677e91820 100644 --- a/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden +++ b/command/connect/envoy/testdata/prometheus-metrics-tls-ca-path.golden @@ -151,9 +151,7 @@ } ], "validationContextSdsSecretConfig": { - "trustedCa": { - "name": "prometheus_validation_context" - } + "name": "prometheus_validation_context" } } } diff --git a/command/config/write/decode_shim.go b/command/helpers/decode_shim.go similarity index 99% rename from command/config/write/decode_shim.go rename to command/helpers/decode_shim.go index c0ac6bf7f9..e7465ed810 100644 --- a/command/config/write/decode_shim.go +++ b/command/helpers/decode_shim.go @@ -1,4 +1,4 @@ -package write +package helpers import ( "encoding/json" diff --git a/command/helpers/helpers.go b/command/helpers/helpers.go index 965f261bd6..56ad6f7d36 100644 --- a/command/helpers/helpers.go +++ b/command/helpers/helpers.go @@ -6,6 +6,12 @@ import ( "io" "io/ioutil" "os" + "time" + + "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/lib/decode" + "github.com/hashicorp/go-multierror" + "github.com/mitchellh/mapstructure" ) func loadFromFile(path string) (string, error) { @@ -59,3 +65,74 @@ func LoadDataSourceNoRaw(data string, testStdin io.Reader) (string, error) { return loadFromFile(data) } + +func ParseConfigEntry(data string) (api.ConfigEntry, error) { + // parse the data + var raw map[string]interface{} + if err := hclDecode(&raw, data); err != nil { + return nil, fmt.Errorf("Failed to decode config entry input: %v", err) + } + + return newDecodeConfigEntry(raw) +} + +// There is a 'structs' variation of this in +// agent/structs/config_entry.go:DecodeConfigEntry +func newDecodeConfigEntry(raw map[string]interface{}) (api.ConfigEntry, error) { + var entry api.ConfigEntry + + kindVal, ok := raw["Kind"] + if !ok { + kindVal, ok = raw["kind"] + } + if !ok { + return nil, fmt.Errorf("Payload does not contain a kind/Kind key at the top level") + } + + if kindStr, ok := kindVal.(string); ok { + newEntry, err := api.MakeConfigEntry(kindStr, "") + if err != nil { + return nil, err + } + entry = newEntry + } else { + return nil, fmt.Errorf("Kind value in payload is not a string") + } + + var md mapstructure.Metadata + decodeConf := &mapstructure.DecoderConfig{ + DecodeHook: mapstructure.ComposeDecodeHookFunc( + decode.HookWeakDecodeFromSlice, + decode.HookTranslateKeys, + mapstructure.StringToTimeDurationHookFunc(), + mapstructure.StringToTimeHookFunc(time.RFC3339), + ), + Metadata: &md, + Result: &entry, + WeaklyTypedInput: true, + } + + decoder, err := mapstructure.NewDecoder(decodeConf) + if err != nil { + return nil, err + } + + if err := decoder.Decode(raw); err != nil { + return nil, err + } + + for _, k := range md.Unused { + switch k { + case "kind", "Kind": + // The kind field is used to determine the target, but doesn't need + // to exist on the target. + continue + } + err = multierror.Append(err, fmt.Errorf("invalid config key %q", k)) + } + if err != nil { + return nil, err + } + + return entry, nil +} diff --git a/command/helpers/helpers_test.go b/command/helpers/helpers_test.go new file mode 100644 index 0000000000..82759159f3 --- /dev/null +++ b/command/helpers/helpers_test.go @@ -0,0 +1,3079 @@ +package helpers + +import ( + "strings" + "testing" + "time" + + "github.com/hashicorp/consul/agent/structs" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/api" +) + +// TestParseConfigEntry is the 'api' mirror image of +// agent/structs/config_entry_test.go:TestDecodeConfigEntry +func TestParseConfigEntry(t *testing.T) { + t.Parallel() + for _, tc := range []struct { + name string + camel, camelJSON string + snake, snakeJSON string + expect api.ConfigEntry + expectJSON api.ConfigEntry + expectErr string + }{ + { + name: "proxy-defaults: extra fields or typo", + snake: ` + kind = "proxy-defaults" + name = "main" + cornfig { + "foo" = 19 + } + `, + camel: ` + Kind = "proxy-defaults" + Name = "main" + Cornfig { + "foo" = 19 + } + `, + snakeJSON: ` + { + "kind": "proxy-defaults", + "name": "main", + "cornfig": { + "foo": 19 + } + } + `, + camelJSON: ` + { + "Kind": "proxy-defaults", + "Name": "main", + "Cornfig": { + "foo": 19 + } + } + `, + expectErr: `invalid config key "cornfig"`, + }, + { + name: "proxy-defaults", + snake: ` + kind = "proxy-defaults" + name = "main" + meta { + "foo" = "bar" + "gir" = "zim" + } + config { + "foo" = 19 + "bar" = "abc" + "moreconfig" { + "moar" = "config" + } + } + mesh_gateway { + mode = "remote" + } + mode = "direct" + transparent_proxy = { + outbound_listener_port = 10101 + dialed_directly = true + } + `, + camel: ` + Kind = "proxy-defaults" + Name = "main" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Config { + "foo" = 19 + "bar" = "abc" + "moreconfig" { + "moar" = "config" + } + } + MeshGateway { + Mode = "remote" + } + Mode = "direct" + TransparentProxy = { + outbound_listener_port = 10101 + dialed_directly = true + } + `, + snakeJSON: ` + { + "kind": "proxy-defaults", + "name": "main", + "meta" : { + "foo": "bar", + "gir": "zim" + }, + "config": { + "foo": 19, + "bar": "abc", + "moreconfig": { + "moar": "config" + } + }, + "mesh_gateway": { + "mode": "remote" + }, + "mode": "direct", + "transparent_proxy": { + "outbound_listener_port": 10101, + "dialed_directly": true + } + } + `, + camelJSON: ` + { + "Kind": "proxy-defaults", + "Name": "main", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "Config": { + "foo": 19, + "bar": "abc", + "moreconfig": { + "moar": "config" + } + }, + "MeshGateway": { + "Mode": "remote" + }, + "Mode": "direct", + "TransparentProxy": { + "OutboundListenerPort": 10101, + "DialedDirectly": true + } + } + `, + expect: &api.ProxyConfigEntry{ + Kind: "proxy-defaults", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Config: map[string]interface{}{ + "foo": 19, + "bar": "abc", + "moreconfig": map[string]interface{}{ + "moar": "config", + }, + }, + MeshGateway: api.MeshGatewayConfig{ + Mode: api.MeshGatewayModeRemote, + }, + Mode: api.ProxyModeDirect, + TransparentProxy: &api.TransparentProxyConfig{ + OutboundListenerPort: 10101, + DialedDirectly: true, + }, + }, + expectJSON: &api.ProxyConfigEntry{ + Kind: "proxy-defaults", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Config: map[string]interface{}{ + "foo": float64(19), // json decoding gives float64 instead of int here + "bar": "abc", + "moreconfig": map[string]interface{}{ + "moar": "config", + }, + }, + MeshGateway: api.MeshGatewayConfig{ + Mode: api.MeshGatewayModeRemote, + }, + Mode: api.ProxyModeDirect, + TransparentProxy: &api.TransparentProxyConfig{ + OutboundListenerPort: 10101, + DialedDirectly: true, + }, + }, + }, + { + name: "terminating-gateway", + snake: ` + kind = "terminating-gateway" + name = "terminating-gw-west" + namespace = "default" + meta { + "foo" = "bar" + "gir" = "zim" + } + services = [ + { + name = "billing" + namespace = "biz" + ca_file = "/etc/ca.crt" + cert_file = "/etc/client.crt" + key_file = "/etc/tls.key" + sni = "mydomain" + }, + { + name = "*" + namespace = "ops" + } + ] + `, + camel: ` + Kind = "terminating-gateway" + Name = "terminating-gw-west" + Namespace = "default" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Services = [ + { + Name = "billing" + Namespace = "biz" + CAFile = "/etc/ca.crt" + CertFile = "/etc/client.crt" + KeyFile = "/etc/tls.key" + SNI = "mydomain" + }, + { + Name = "*" + Namespace = "ops" + } + ] + `, + snakeJSON: ` + { + "kind": "terminating-gateway", + "name": "terminating-gw-west", + "namespace": "default", + "meta" : { + "foo": "bar", + "gir": "zim" + }, + "services": [ + { + "name": "billing", + "namespace": "biz", + "ca_file": "/etc/ca.crt", + "cert_file": "/etc/client.crt", + "key_file": "/etc/tls.key", + "sni": "mydomain" + }, + { + "name": "*", + "namespace": "ops" + } + ] + } + `, + camelJSON: ` + { + "Kind": "terminating-gateway", + "Name": "terminating-gw-west", + "Namespace": "default", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "Services": [ + { + "Name": "billing", + "Namespace": "biz", + "CAFile": "/etc/ca.crt", + "CertFile": "/etc/client.crt", + "KeyFile": "/etc/tls.key", + "SNI": "mydomain" + }, + { + "Name": "*", + "Namespace": "ops" + } + ] + } + `, + expect: &api.TerminatingGatewayConfigEntry{ + Kind: "terminating-gateway", + Name: "terminating-gw-west", + Namespace: "default", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Services: []api.LinkedService{ + { + Name: "billing", + Namespace: "biz", + CAFile: "/etc/ca.crt", + CertFile: "/etc/client.crt", + KeyFile: "/etc/tls.key", + SNI: "mydomain", + }, + { + Name: "*", + Namespace: "ops", + }, + }, + }, + expectJSON: &api.TerminatingGatewayConfigEntry{ + Kind: "terminating-gateway", + Name: "terminating-gw-west", + Namespace: "default", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Services: []api.LinkedService{ + { + Name: "billing", + Namespace: "biz", + CAFile: "/etc/ca.crt", + CertFile: "/etc/client.crt", + KeyFile: "/etc/tls.key", + SNI: "mydomain", + }, + { + Name: "*", + Namespace: "ops", + }, + }, + }, + }, + { + name: "service-defaults: kitchen sink (upstreams edition)", + snake: ` + kind = "service-defaults" + name = "main" + meta { + "foo" = "bar" + "gir" = "zim" + } + protocol = "http" + external_sni = "abc-123" + mesh_gateway { + mode = "remote" + } + mode = "direct" + transparent_proxy = { + outbound_listener_port = 10101 + dialed_directly = true + } + upstream_config { + overrides = [ + { + name = "redis" + passive_health_check { + max_failures = 3 + interval = "2s" + } + envoy_listener_json = "{ \"listener-foo\": 5 }" + envoy_cluster_json = "{ \"cluster-bar\": 5 }" + protocol = "grpc" + connect_timeout_ms = 6543 + }, + { + name = "finance--billing" + mesh_gateway { + mode = "remote" + } + limits { + max_connections = 1111 + max_pending_requests = 2222 + max_concurrent_requests = 3333 + } + } + ] + defaults { + envoy_cluster_json = "zip" + envoy_listener_json = "zop" + connect_timeout_ms = 5000 + protocol = "http" + limits { + max_connections = 3 + max_pending_requests = 4 + max_concurrent_requests = 5 + } + passive_health_check { + max_failures = 5 + interval = "4s" + } + } + } + `, + camel: ` + Kind = "service-defaults" + Name = "main" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Protocol = "http" + ExternalSNI = "abc-123" + MeshGateway { + Mode = "remote" + } + Mode = "direct" + TransparentProxy = { + outbound_listener_port = 10101 + dialed_directly = true + } + UpstreamConfig { + Overrides = [ + { + Name = "redis" + PassiveHealthCheck { + MaxFailures = 3 + Interval = "2s" + } + EnvoyListenerJson = "{ \"listener-foo\": 5 }" + EnvoyClusterJson = "{ \"cluster-bar\": 5 }" + Protocol = "grpc" + ConnectTimeoutMs = 6543 + }, + { + Name = "finance--billing" + MeshGateway { + Mode = "remote" + } + Limits { + MaxConnections = 1111 + MaxPendingRequests = 2222 + MaxConcurrentRequests = 3333 + } + } + ] + Defaults { + EnvoyClusterJson = "zip" + EnvoyListenerJson = "zop" + ConnectTimeoutMs = 5000 + Protocol = "http" + Limits { + MaxConnections = 3 + MaxPendingRequests = 4 + MaxConcurrentRequests = 5 + } + PassiveHealthCheck { + MaxFailures = 5 + Interval = "4s" + } + } + } + `, + snakeJSON: ` + { + "kind": "service-defaults", + "name": "main", + "meta" : { + "foo": "bar", + "gir": "zim" + }, + "protocol": "http", + "external_sni": "abc-123", + "mesh_gateway": { + "mode": "remote" + }, + "mode": "direct", + "transparent_proxy": { + "outbound_listener_port": 10101, + "dialed_directly": true + }, + "upstream_config": { + "overrides": [ + { + "name": "redis", + "passive_health_check": { + "max_failures": 3, + "interval": "2s" + }, + "envoy_listener_json": "{ \"listener-foo\": 5 }", + "envoy_cluster_json": "{ \"cluster-bar\": 5 }", + "protocol": "grpc", + "connect_timeout_ms": 6543 + }, + { + "name": "finance--billing", + "mesh_gateway": { + "mode": "remote" + }, + "limits": { + "max_connections": 1111, + "max_pending_requests": 2222, + "max_concurrent_requests": 3333 + } + } + ], + "defaults": { + "envoy_cluster_json": "zip", + "envoy_listener_json": "zop", + "connect_timeout_ms": 5000, + "protocol": "http", + "limits": { + "max_connections": 3, + "max_pending_requests": 4, + "max_concurrent_requests": 5 + }, + "passive_health_check": { + "max_failures": 5, + "interval": "4s" + } + } + } + } + `, + camelJSON: ` + { + "Kind": "service-defaults", + "Name": "main", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "Protocol": "http", + "ExternalSNI": "abc-123", + "MeshGateway": { + "Mode": "remote" + }, + "Mode": "direct", + "TransparentProxy": { + "OutboundListenerPort": 10101, + "DialedDirectly": true + }, + "UpstreamConfig": { + "Overrides": [ + { + "Name": "redis", + "PassiveHealthCheck": { + "MaxFailures": 3, + "Interval": "2s" + }, + "EnvoyListenerJson": "{ \"listener-foo\": 5 }", + "EnvoyClusterJson": "{ \"cluster-bar\": 5 }", + "Protocol": "grpc", + "ConnectTimeoutMs": 6543 + }, + { + "Name": "finance--billing", + "MeshGateway": { + "Mode": "remote" + }, + "Limits": { + "MaxConnections": 1111, + "MaxPendingRequests": 2222, + "MaxConcurrentRequests": 3333 + } + } + ], + "Defaults": { + "EnvoyClusterJson": "zip", + "EnvoyListenerJson": "zop", + "ConnectTimeoutMs": 5000, + "Protocol": "http", + "Limits": { + "MaxConnections": 3, + "MaxPendingRequests": 4, + "MaxConcurrentRequests": 5 + }, + "PassiveHealthCheck": { + "MaxFailures": 5, + "Interval": "4s" + } + } + } + } + `, + expect: &api.ServiceConfigEntry{ + Kind: "service-defaults", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Protocol: "http", + ExternalSNI: "abc-123", + MeshGateway: api.MeshGatewayConfig{ + Mode: api.MeshGatewayModeRemote, + }, + Mode: api.ProxyModeDirect, + TransparentProxy: &api.TransparentProxyConfig{ + OutboundListenerPort: 10101, + DialedDirectly: true, + }, + UpstreamConfig: &api.UpstreamConfiguration{ + Overrides: []*api.UpstreamConfig{ + { + Name: "redis", + PassiveHealthCheck: &api.PassiveHealthCheck{ + MaxFailures: 3, + Interval: 2 * time.Second, + }, + EnvoyListenerJSON: `{ "listener-foo": 5 }`, + EnvoyClusterJSON: `{ "cluster-bar": 5 }`, + Protocol: "grpc", + ConnectTimeoutMs: 6543, + }, + { + Name: "finance--billing", + MeshGateway: api.MeshGatewayConfig{ + Mode: "remote", + }, + Limits: &api.UpstreamLimits{ + MaxConnections: intPointer(1111), + MaxPendingRequests: intPointer(2222), + MaxConcurrentRequests: intPointer(3333), + }, + }, + }, + Defaults: &api.UpstreamConfig{ + EnvoyClusterJSON: "zip", + EnvoyListenerJSON: "zop", + Protocol: "http", + ConnectTimeoutMs: 5000, + Limits: &api.UpstreamLimits{ + MaxConnections: intPointer(3), + MaxPendingRequests: intPointer(4), + MaxConcurrentRequests: intPointer(5), + }, + PassiveHealthCheck: &api.PassiveHealthCheck{ + MaxFailures: 5, + Interval: 4 * time.Second, + }, + }, + }, + }, + }, + { + name: "service-defaults: kitchen sink (destination edition)", + snake: ` + kind = "service-defaults" + name = "main" + meta { + "foo" = "bar" + "gir" = "zim" + } + protocol = "grpc" + mesh_gateway { + mode = "remote" + } + mode = "transparent" + transparent_proxy = { + outbound_listener_port = 10101 + dialed_directly = true + } + destination = { + address = "10.0.0.0/16", + port = 443 + } + `, + camel: ` + Kind = "service-defaults" + Name = "main" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Protocol = "grpc" + MeshGateway { + Mode = "remote" + } + Mode = "transparent" + TransparentProxy = { + outbound_listener_port = 10101 + dialed_directly = true + } + Destination = { + Address = "10.0.0.0/16", + Port = 443 + } + `, + snakeJSON: ` + { + "kind": "service-defaults", + "name": "main", + "meta" : { + "foo": "bar", + "gir": "zim" + }, + "protocol": "grpc", + "mesh_gateway": { + "mode": "remote" + }, + "mode": "transparent", + "transparent_proxy": { + "outbound_listener_port": 10101, + "dialed_directly": true + }, + "destination": { + "address": "10.0.0.0/16", + "port": 443 + } + } + `, + camelJSON: ` + { + "Kind": "service-defaults", + "Name": "main", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "Protocol": "grpc", + "MeshGateway": { + "Mode": "remote" + }, + "Mode": "transparent", + "TransparentProxy": { + "OutboundListenerPort": 10101, + "DialedDirectly": true + }, + "Destination": { + "Address": "10.0.0.0/16", + "Port": 443 + } + } + `, + expect: &api.ServiceConfigEntry{ + Kind: "service-defaults", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Protocol: "grpc", + MeshGateway: api.MeshGatewayConfig{ + Mode: api.MeshGatewayModeRemote, + }, + Mode: api.ProxyModeTransparent, + TransparentProxy: &api.TransparentProxyConfig{ + OutboundListenerPort: 10101, + DialedDirectly: true, + }, + Destination: &api.DestinationConfig{ + Address: "10.0.0.0/16", + Port: 443, + }, + }, + }, + { + name: "service-router: kitchen sink", + snake: ` + kind = "service-router" + name = "main" + partition = "pepper" + meta { + "foo" = "bar" + "gir" = "zim" + } + routes = [ + { + match { + http { + path_exact = "/foo" + header = [ + { + name = "debug1" + present = true + }, + { + name = "debug2" + present = false + invert = true + }, + { + name = "debug3" + exact = "1" + }, + { + name = "debug4" + prefix = "aaa" + }, + { + name = "debug5" + suffix = "bbb" + }, + { + name = "debug6" + regex = "a.*z" + }, + ] + } + } + destination { + service = "carrot" + service_subset = "kale" + namespace = "leek" + partition = "chard" + prefix_rewrite = "/alternate" + request_timeout = "99s" + num_retries = 12345 + retry_on_connect_failure = true + retry_on_status_codes = [401, 209] + } + }, + { + match { + http { + path_prefix = "/foo" + methods = [ "GET", "DELETE" ] + query_param = [ + { + name = "hack1" + present = true + }, + { + name = "hack2" + exact = "1" + }, + { + name = "hack3" + regex = "a.*z" + }, + ] + } + } + }, + { + match { + http { + path_regex = "/foo" + } + } + }, + ] + `, + camel: ` + Kind = "service-router" + Name = "main" + Partition = "pepper" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Routes = [ + { + Match { + HTTP { + PathExact = "/foo" + Header = [ + { + Name = "debug1" + Present = true + }, + { + Name = "debug2" + Present = false + Invert = true + }, + { + Name = "debug3" + Exact = "1" + }, + { + Name = "debug4" + Prefix = "aaa" + }, + { + Name = "debug5" + Suffix = "bbb" + }, + { + Name = "debug6" + Regex = "a.*z" + }, + ] + } + } + Destination { + Service = "carrot" + ServiceSubset = "kale" + Namespace = "leek" + Partition = "chard" + PrefixRewrite = "/alternate" + RequestTimeout = "99s" + NumRetries = 12345 + RetryOnConnectFailure = true + RetryOnStatusCodes = [401, 209] + } + }, + { + Match { + HTTP { + PathPrefix = "/foo" + Methods = [ "GET", "DELETE" ] + QueryParam = [ + { + Name = "hack1" + Present = true + }, + { + Name = "hack2" + Exact = "1" + }, + { + Name = "hack3" + Regex = "a.*z" + }, + ] + } + } + }, + { + Match { + HTTP { + PathRegex = "/foo" + } + } + }, + ] + `, + snakeJSON: ` + { + "kind": "service-router", + "name": "main", + "partition": "pepper", + "meta" : { + "foo": "bar", + "gir": "zim" + }, + "routes": [ + { + "match": { + "http": { + "path_exact": "/foo", + "header": [ + { + "name": "debug1", + "present": true + }, + { + "name": "debug2", + "present": false, + "invert": true + }, + { + "name": "debug3", + "exact": "1" + }, + { + "name": "debug4", + "prefix": "aaa" + }, + { + "name": "debug5", + "suffix": "bbb" + }, + { + "name": "debug6", + "regex": "a.*z" + } + ] + } + }, + "destination": { + "service": "carrot", + "service_subset": "kale", + "namespace": "leek", + "partition": "chard", + "prefix_rewrite": "/alternate", + "request_timeout": "99s", + "num_retries": 12345, + "retry_on_connect_failure": true, + "retry_on_status_codes": [ + 401, + 209 + ] + } + }, + { + "match": { + "http": { + "path_prefix": "/foo", + "methods": [ + "GET", + "DELETE" + ], + "query_param": [ + { + "name": "hack1", + "present": true + }, + { + "name": "hack2", + "exact": "1" + }, + { + "name": "hack3", + "regex": "a.*z" + } + ] + } + } + }, + { + "match": { + "http": { + "path_regex": "/foo" + } + } + } + ] + } + `, + camelJSON: ` + { + "Kind": "service-router", + "Name": "main", + "Partition": "pepper", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "Routes": [ + { + "Match": { + "HTTP": { + "PathExact": "/foo", + "Header": [ + { + "Name": "debug1", + "Present": true + }, + { + "Name": "debug2", + "Present": false, + "Invert": true + }, + { + "Name": "debug3", + "Exact": "1" + }, + { + "Name": "debug4", + "Prefix": "aaa" + }, + { + "Name": "debug5", + "Suffix": "bbb" + }, + { + "Name": "debug6", + "Regex": "a.*z" + } + ] + } + }, + "Destination": { + "Service": "carrot", + "ServiceSubset": "kale", + "Namespace": "leek", + "Partition": "chard", + "PrefixRewrite": "/alternate", + "RequestTimeout": "99s", + "NumRetries": 12345, + "RetryOnConnectFailure": true, + "RetryOnStatusCodes": [ + 401, + 209 + ] + } + }, + { + "Match": { + "HTTP": { + "PathPrefix": "/foo", + "Methods": [ + "GET", + "DELETE" + ], + "QueryParam": [ + { + "Name": "hack1", + "Present": true + }, + { + "Name": "hack2", + "Exact": "1" + }, + { + "Name": "hack3", + "Regex": "a.*z" + } + ] + } + } + }, + { + "Match": { + "HTTP": { + "PathRegex": "/foo" + } + } + } + ] + } + `, + expect: &api.ServiceRouterConfigEntry{ + Kind: "service-router", + Name: "main", + Partition: "pepper", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Routes: []api.ServiceRoute{ + { + Match: &api.ServiceRouteMatch{ + HTTP: &api.ServiceRouteHTTPMatch{ + PathExact: "/foo", + Header: []api.ServiceRouteHTTPMatchHeader{ + { + Name: "debug1", + Present: true, + }, + { + Name: "debug2", + Present: false, + Invert: true, + }, + { + Name: "debug3", + Exact: "1", + }, + { + Name: "debug4", + Prefix: "aaa", + }, + { + Name: "debug5", + Suffix: "bbb", + }, + { + Name: "debug6", + Regex: "a.*z", + }, + }, + }, + }, + Destination: &api.ServiceRouteDestination{ + Service: "carrot", + ServiceSubset: "kale", + Namespace: "leek", + Partition: "chard", + PrefixRewrite: "/alternate", + RequestTimeout: 99 * time.Second, + NumRetries: 12345, + RetryOnConnectFailure: true, + RetryOnStatusCodes: []uint32{401, 209}, + }, + }, + { + Match: &api.ServiceRouteMatch{ + HTTP: &api.ServiceRouteHTTPMatch{ + PathPrefix: "/foo", + Methods: []string{"GET", "DELETE"}, + QueryParam: []api.ServiceRouteHTTPMatchQueryParam{ + { + Name: "hack1", + Present: true, + }, + { + Name: "hack2", + Exact: "1", + }, + { + Name: "hack3", + Regex: "a.*z", + }, + }, + }, + }, + }, + { + Match: &api.ServiceRouteMatch{ + HTTP: &api.ServiceRouteHTTPMatch{ + PathRegex: "/foo", + }, + }, + }, + }, + }, + }, + { + name: "service-splitter: kitchen sink", + snake: ` + kind = "service-splitter" + name = "main" + partition = "east" + meta { + "foo" = "bar" + "gir" = "zim" + } + splits = [ + { + weight = 97.1 + service_subset = "v1" + }, + { + weight = 2 + service_subset = "v2" + }, + { + weight = 0.9 + service = "other" + namespace = "alt" + partition = "west" + }, + ] + `, + camel: ` + Kind = "service-splitter" + Name = "main" + Partition = "east" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Splits = [ + { + Weight = 97.1 + ServiceSubset = "v1" + }, + { + Weight = 2, + ServiceSubset = "v2" + }, + { + Weight = 0.9 + Service = "other" + Namespace = "alt" + Partition = "west" + }, + ] + `, + snakeJSON: ` + { + "kind": "service-splitter", + "name": "main", + "partition": "east", + "meta" : { + "foo": "bar", + "gir": "zim" + }, + "splits": [ + { + "weight": 97.1, + "service_subset": "v1" + }, + { + "weight": 2, + "service_subset": "v2" + }, + { + "weight": 0.9, + "service": "other", + "namespace": "alt", + "partition": "west" + } + ] + } + `, + camelJSON: ` + { + "Kind": "service-splitter", + "Name": "main", + "Partition": "east", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "Splits": [ + { + "Weight": 97.1, + "ServiceSubset": "v1" + }, + { + "Weight": 2, + "ServiceSubset": "v2" + }, + { + "Weight": 0.9, + "Service": "other", + "Namespace": "alt", + "Partition": "west" + } + ] + } + `, + expect: &api.ServiceSplitterConfigEntry{ + Kind: api.ServiceSplitter, + Name: "main", + Partition: "east", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Splits: []api.ServiceSplit{ + { + Weight: 97.1, + ServiceSubset: "v1", + }, + { + Weight: 2, + ServiceSubset: "v2", + }, + { + Weight: 0.9, + Service: "other", + Namespace: "alt", + Partition: "west", + }, + }, + }, + }, + { + name: "service-resolver: subsets with failover", + snake: ` + kind = "service-resolver" + name = "main" + meta { + "foo" = "bar" + "gir" = "zim" + } + default_subset = "v1" + connect_timeout = "15s" + subsets = { + "v1" = { + filter = "Service.Meta.version == v1" + }, + "v2" = { + filter = "Service.Meta.version == v2" + only_passing = true + }, + } + failover = { + "v2" = { + service = "failcopy" + service_subset = "sure" + namespace = "neighbor" + datacenters = ["dc5", "dc14"] + }, + "*" = { + datacenters = ["dc7"] + } + }`, + camel: ` + Kind = "service-resolver" + Name = "main" + Meta { + "foo" = "bar" + "gir" = "zim" + } + DefaultSubset = "v1" + ConnectTimeout = "15s" + Subsets = { + "v1" = { + Filter = "Service.Meta.version == v1" + }, + "v2" = { + Filter = "Service.Meta.version == v2" + OnlyPassing = true + }, + } + Failover = { + "v2" = { + Service = "failcopy" + ServiceSubset = "sure" + Namespace = "neighbor" + Datacenters = ["dc5", "dc14"] + }, + "*" = { + Datacenters = ["dc7"] + } + }`, + snakeJSON: ` + { + "kind": "service-resolver", + "name": "main", + "meta" : { + "foo": "bar", + "gir": "zim" + }, + "default_subset": "v1", + "connect_timeout": "15s", + "subsets": { + "v1": { + "filter": "Service.Meta.version == v1" + }, + "v2": { + "filter": "Service.Meta.version == v2", + "only_passing": true + } + }, + "failover": { + "v2": { + "service": "failcopy", + "service_subset": "sure", + "namespace": "neighbor", + "datacenters": [ + "dc5", + "dc14" + ] + }, + "*": { + "datacenters": [ + "dc7" + ] + } + } + } + `, + camelJSON: ` + { + "Kind": "service-resolver", + "Name": "main", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "DefaultSubset": "v1", + "ConnectTimeout": "15s", + "Subsets": { + "v1": { + "Filter": "Service.Meta.version == v1" + }, + "v2": { + "Filter": "Service.Meta.version == v2", + "OnlyPassing": true + } + }, + "Failover": { + "v2": { + "Service": "failcopy", + "ServiceSubset": "sure", + "Namespace": "neighbor", + "Datacenters": [ + "dc5", + "dc14" + ] + }, + "*": { + "Datacenters": [ + "dc7" + ] + } + } + } + `, + expect: &api.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + DefaultSubset: "v1", + ConnectTimeout: 15 * time.Second, + Subsets: map[string]api.ServiceResolverSubset{ + "v1": { + Filter: "Service.Meta.version == v1", + }, + "v2": { + Filter: "Service.Meta.version == v2", + OnlyPassing: true, + }, + }, + Failover: map[string]api.ServiceResolverFailover{ + "v2": { + Service: "failcopy", + ServiceSubset: "sure", + Namespace: "neighbor", + Datacenters: []string{"dc5", "dc14"}, + }, + "*": { + Datacenters: []string{"dc7"}, + }, + }, + }, + }, + { + name: "service-resolver: redirect", + snake: ` + kind = "service-resolver" + name = "main" + partition = "east" + redirect { + service = "other" + service_subset = "backup" + namespace = "alt" + partition = "west" + datacenter = "dc9" + } + `, + camel: ` + Kind = "service-resolver" + Name = "main" + Partition = "east" + Redirect { + Service = "other" + ServiceSubset = "backup" + Namespace = "alt" + Partition = "west" + Datacenter = "dc9" + } + `, + snakeJSON: ` + { + "kind": "service-resolver", + "name": "main", + "partition": "east", + "redirect": { + "service": "other", + "service_subset": "backup", + "namespace": "alt", + "partition": "west", + "datacenter": "dc9" + } + } + `, + camelJSON: ` + { + "Kind": "service-resolver", + "Name": "main", + "Partition": "east", + "Redirect": { + "Service": "other", + "ServiceSubset": "backup", + "Namespace": "alt", + "Partition": "west", + "Datacenter": "dc9" + } + } + `, + expect: &api.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + Partition: "east", + Redirect: &api.ServiceResolverRedirect{ + Service: "other", + ServiceSubset: "backup", + Namespace: "alt", + Partition: "west", + Datacenter: "dc9", + }, + }, + }, + { + name: "service-resolver: default", + snake: ` + kind = "service-resolver" + name = "main" + `, + camel: ` + Kind = "service-resolver" + Name = "main" + `, + snakeJSON: ` + { + "kind": "service-resolver", + "name": "main" + } + `, + camelJSON: ` + { + "Kind": "service-resolver", + "Name": "main" + } + `, + expect: &api.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + }, + }, + { + name: "service-resolver: envoy hash lb kitchen sink", + snake: ` + kind = "service-resolver" + name = "main" + load_balancer = { + policy = "ring_hash" + ring_hash_config = { + minimum_ring_size = 1 + maximum_ring_size = 2 + } + hash_policies = [ + { + field = "cookie" + field_value = "good-cookie" + cookie_config = { + ttl = "1s" + path = "/oven" + } + terminal = true + }, + { + field = "cookie" + field_value = "less-good-cookie" + cookie_config = { + session = true + path = "/toaster" + } + terminal = true + }, + { + field = "header" + field_value = "x-user-id" + }, + { + source_ip = true + } + ] + } + `, + camel: ` + Kind = "service-resolver" + Name = "main" + LoadBalancer = { + Policy = "ring_hash" + RingHashConfig = { + MinimumRingSize = 1 + MaximumRingSize = 2 + } + HashPolicies = [ + { + Field = "cookie" + FieldValue = "good-cookie" + CookieConfig = { + TTL = "1s" + Path = "/oven" + } + Terminal = true + }, + { + Field = "cookie" + FieldValue = "less-good-cookie" + CookieConfig = { + Session = true + Path = "/toaster" + } + Terminal = true + }, + { + Field = "header" + FieldValue = "x-user-id" + }, + { + SourceIP = true + } + ] + } + `, + snakeJSON: ` + { + "kind": "service-resolver", + "name": "main", + "load_balancer": { + "policy": "ring_hash", + "ring_hash_config": { + "minimum_ring_size": 1, + "maximum_ring_size": 2 + }, + "hash_policies": [ + { + "field": "cookie", + "field_value": "good-cookie", + "cookie_config": { + "ttl": "1s", + "path": "/oven" + }, + "terminal": true + }, + { + "field": "cookie", + "field_value": "less-good-cookie", + "cookie_config": { + "session": true, + "path": "/toaster" + }, + "terminal": true + }, + { + "field": "header", + "field_value": "x-user-id" + }, + { + "source_ip": true + } + ] + } + } + `, + camelJSON: ` + { + "Kind": "service-resolver", + "Name": "main", + "LoadBalancer": { + "Policy": "ring_hash", + "RingHashConfig": { + "MinimumRingSize": 1, + "MaximumRingSize": 2 + }, + "HashPolicies": [ + { + "Field": "cookie", + "FieldValue": "good-cookie", + "CookieConfig": { + "TTL": "1s", + "Path": "/oven" + }, + "Terminal": true + }, + { + "Field": "cookie", + "FieldValue": "less-good-cookie", + "CookieConfig": { + "Session": true, + "Path": "/toaster" + }, + "Terminal": true + }, + { + "Field": "header", + "FieldValue": "x-user-id" + }, + { + "SourceIP": true + } + ] + } + } + `, + expect: &api.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + LoadBalancer: &api.LoadBalancer{ + Policy: structs.LBPolicyRingHash, + RingHashConfig: &api.RingHashConfig{ + MinimumRingSize: 1, + MaximumRingSize: 2, + }, + HashPolicies: []api.HashPolicy{ + { + Field: structs.HashPolicyCookie, + FieldValue: "good-cookie", + CookieConfig: &api.CookieConfig{ + TTL: 1 * time.Second, + Path: "/oven", + }, + Terminal: true, + }, + { + Field: structs.HashPolicyCookie, + FieldValue: "less-good-cookie", + CookieConfig: &api.CookieConfig{ + Session: true, + Path: "/toaster", + }, + Terminal: true, + }, + { + Field: structs.HashPolicyHeader, + FieldValue: "x-user-id", + }, + { + SourceIP: true, + }, + }, + }, + }, + }, + { + name: "service-resolver: envoy least request kitchen sink", + snake: ` + kind = "service-resolver" + name = "main" + load_balancer = { + policy = "least_request" + least_request_config = { + choice_count = 2 + } + } + `, + camel: ` + Kind = "service-resolver" + Name = "main" + LoadBalancer = { + Policy = "least_request" + LeastRequestConfig = { + ChoiceCount = 2 + } + } + `, + snakeJSON: ` + { + "kind": "service-resolver", + "name": "main", + "load_balancer": { + "policy": "least_request", + "least_request_config": { + "choice_count": 2 + } + } + } + `, + camelJSON: ` + { + "Kind": "service-resolver", + "Name": "main", + "LoadBalancer": { + "Policy": "least_request", + "LeastRequestConfig": { + "ChoiceCount": 2 + } + } + } + `, + expect: &api.ServiceResolverConfigEntry{ + Kind: "service-resolver", + Name: "main", + LoadBalancer: &api.LoadBalancer{ + Policy: structs.LBPolicyLeastRequest, + LeastRequestConfig: &api.LeastRequestConfig{ + ChoiceCount: 2, + }, + }, + }, + }, + { + name: "expose paths: kitchen sink proxy defaults", + snake: ` + kind = "proxy-defaults" + name = "global" + expose = { + checks = true + paths = [ + { + local_path_port = 8080 + listener_port = 21500 + path = "/healthz" + protocol = "http2" + }, + { + local_path_port = 8000 + listener_port = 21501 + path = "/metrics" + protocol = "http" + } + ] + }`, + camel: ` + Kind = "proxy-defaults" + Name = "global" + Expose = { + Checks = true + Paths = [ + { + LocalPathPort = 8080 + ListenerPort = 21500 + Path = "/healthz" + Protocol = "http2" + }, + { + LocalPathPort = 8000 + ListenerPort = 21501 + Path = "/metrics" + Protocol = "http" + } + ] + }`, + snakeJSON: ` + { + "kind": "proxy-defaults", + "name": "global", + "expose": { + "checks": true, + "paths": [ + { + "local_path_port": 8080, + "listener_port": 21500, + "path": "/healthz", + "protocol": "http2" + }, + { + "local_path_port": 8000, + "listener_port": 21501, + "path": "/metrics", + "protocol": "http" + } + ] + } + } + `, + camelJSON: ` + { + "Kind": "proxy-defaults", + "Name": "global", + "Expose": { + "Checks": true, + "Paths": [ + { + "LocalPathPort": 8080, + "ListenerPort": 21500, + "Path": "/healthz", + "Protocol": "http2" + }, + { + "LocalPathPort": 8000, + "ListenerPort": 21501, + "Path": "/metrics", + "Protocol": "http" + } + ] + } + } + `, + expect: &api.ProxyConfigEntry{ + Kind: "proxy-defaults", + Name: "global", + Expose: api.ExposeConfig{ + Checks: true, + Paths: []api.ExposePath{ + { + ListenerPort: 21500, + Path: "/healthz", + LocalPathPort: 8080, + Protocol: "http2", + }, + { + ListenerPort: 21501, + Path: "/metrics", + LocalPathPort: 8000, + Protocol: "http", + }, + }, + }, + }, + }, + { + name: "expose paths: kitchen sink service defaults", + snake: ` + kind = "service-defaults" + name = "web" + expose = { + checks = true + paths = [ + { + local_path_port = 8080 + listener_port = 21500 + path = "/healthz" + protocol = "http2" + }, + { + local_path_port = 8000 + listener_port = 21501 + path = "/metrics" + protocol = "http" + } + ] + }`, + camel: ` + Kind = "service-defaults" + Name = "web" + Expose = { + Checks = true + Paths = [ + { + LocalPathPort = 8080 + ListenerPort = 21500 + Path = "/healthz" + Protocol = "http2" + }, + { + LocalPathPort = 8000 + ListenerPort = 21501 + Path = "/metrics" + Protocol = "http" + } + ] + }`, + snakeJSON: ` + { + "kind": "service-defaults", + "name": "web", + "expose": { + "checks": true, + "paths": [ + { + "local_path_port": 8080, + "listener_port": 21500, + "path": "/healthz", + "protocol": "http2" + }, + { + "local_path_port": 8000, + "listener_port": 21501, + "path": "/metrics", + "protocol": "http" + } + ] + } + } + `, + camelJSON: ` + { + "Kind": "service-defaults", + "Name": "web", + "Expose": { + "Checks": true, + "Paths": [ + { + "LocalPathPort": 8080, + "ListenerPort": 21500, + "Path": "/healthz", + "Protocol": "http2" + }, + { + "LocalPathPort": 8000, + "ListenerPort": 21501, + "Path": "/metrics", + "Protocol": "http" + } + ] + } + } + `, + expect: &api.ServiceConfigEntry{ + Kind: "service-defaults", + Name: "web", + Expose: api.ExposeConfig{ + Checks: true, + Paths: []api.ExposePath{ + { + ListenerPort: 21500, + Path: "/healthz", + LocalPathPort: 8080, + Protocol: "http2", + }, + { + ListenerPort: 21501, + Path: "/metrics", + LocalPathPort: 8000, + Protocol: "http", + }, + }, + }, + }, + }, + { + // TODO(rb): test SDS stuff here in both places (global/service) + name: "ingress-gateway: kitchen sink", + snake: ` + kind = "ingress-gateway" + name = "ingress-web" + meta { + "foo" = "bar" + "gir" = "zim" + } + tls { + enabled = true + tls_min_version = "TLSv1_1" + tls_max_version = "TLSv1_2" + cipher_suites = [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + } + listeners = [ + { + port = 8080 + protocol = "http" + services = [ + { + name = "web" + hosts = ["test.example.com"] + }, + { + name = "db" + namespace = "foo" + } + ] + } + ] + `, + camel: ` + Kind = "ingress-gateway" + Name = "ingress-web" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Tls { + Enabled = true + TLSMinVersion = "TLSv1_1" + TLSMaxVersion = "TLSv1_2" + CipherSuites = [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + } + Listeners = [ + { + Port = 8080 + Protocol = "http" + Services = [ + { + Name = "web" + Hosts = ["test.example.com"] + }, + { + Name = "db" + Namespace = "foo" + } + ] + } + ] + `, + snakeJSON: ` + { + "kind": "ingress-gateway", + "name": "ingress-web", + "meta" : { + "foo": "bar", + "gir": "zim" + }, + "tls": { + "enabled": true, + "tls_min_version": "TLSv1_1", + "tls_max_version": "TLSv1_2", + "cipher_suites": [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + }, + "listeners": [ + { + "port": 8080, + "protocol": "http", + "services": [ + { + "name": "web", + "hosts": ["test.example.com"] + }, + { + "name": "db", + "namespace": "foo" + } + ] + } + ] + } + `, + camelJSON: ` + { + "Kind": "ingress-gateway", + "Name": "ingress-web", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "TLS": { + "Enabled": true, + "TLSMinVersion": "TLSv1_1", + "TLSMaxVersion": "TLSv1_2", + "CipherSuites": [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + }, + "Listeners": [ + { + "Port": 8080, + "Protocol": "http", + "Services": [ + { + "Name": "web", + "Hosts": ["test.example.com"] + }, + { + "Name": "db", + "Namespace": "foo" + } + ] + } + ] + } + `, + expect: &api.IngressGatewayConfigEntry{ + Kind: "ingress-gateway", + Name: "ingress-web", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + TLS: api.GatewayTLSConfig{ + Enabled: true, + TLSMinVersion: "TLSv1_1", + TLSMaxVersion: "TLSv1_2", + CipherSuites: []string{ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + }, + }, + Listeners: []api.IngressListener{ + { + Port: 8080, + Protocol: "http", + Services: []api.IngressService{ + { + Name: "web", + Hosts: []string{"test.example.com"}, + }, + { + Name: "db", + Namespace: "foo", + }, + }, + }, + }, + }, + }, + { + name: "service-intentions: kitchen sink", + snake: ` + kind = "service-intentions" + name = "web" + meta { + "foo" = "bar" + "gir" = "zim" + } + sources = [ + { + name = "foo" + action = "deny" + type = "consul" + description = "foo desc" + }, + { + name = "bar" + action = "allow" + description = "bar desc" + }, + { + name = "l7" + permissions = [ + { + action = "deny" + http { + path_exact = "/admin" + header = [ + { + name = "hdr-present" + present = true + }, + { + name = "hdr-exact" + exact = "exact" + }, + { + name = "hdr-prefix" + prefix = "prefix" + }, + { + name = "hdr-suffix" + suffix = "suffix" + }, + { + name = "hdr-regex" + regex = "regex" + }, + { + name = "hdr-absent" + present = true + invert = true + } + ] + } + }, + { + action = "allow" + http { + path_prefix = "/v3/" + } + }, + { + action = "allow" + http { + path_regex = "/v[12]/.*" + methods = ["GET", "POST"] + } + } + ] + } + ] + sources { + name = "*" + action = "deny" + description = "wild desc" + } + `, + camel: ` + Kind = "service-intentions" + Name = "web" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Sources = [ + { + Name = "foo" + Action = "deny" + Type = "consul" + Description = "foo desc" + }, + { + Name = "bar" + Action = "allow" + Description = "bar desc" + }, + { + Name = "l7" + Permissions = [ + { + Action = "deny" + HTTP { + PathExact = "/admin" + Header = [ + { + Name = "hdr-present" + Present = true + }, + { + Name = "hdr-exact" + Exact = "exact" + }, + { + Name = "hdr-prefix" + Prefix = "prefix" + }, + { + Name = "hdr-suffix" + Suffix = "suffix" + }, + { + Name = "hdr-regex" + Regex = "regex" + }, + { + Name = "hdr-absent" + Present = true + Invert = true + } + ] + } + }, + { + Action = "allow" + HTTP { + PathPrefix = "/v3/" + } + }, + { + Action = "allow" + HTTP { + PathRegex = "/v[12]/.*" + Methods = ["GET", "POST"] + } + } + ] + } + ] + Sources { + Name = "*" + Action = "deny" + Description = "wild desc" + } + `, + snakeJSON: ` + { + "kind": "service-intentions", + "name": "web", + "meta": { + "foo": "bar", + "gir": "zim" + }, + "sources": [ + { + "name": "foo", + "action": "deny", + "type": "consul", + "description": "foo desc" + }, + { + "name": "bar", + "action": "allow", + "description": "bar desc" + }, + { + "name": "l7", + "permissions": [ + { + "action": "deny", + "http": { + "path_exact": "/admin", + "header": [ + { + "name": "hdr-present", + "present": true + }, + { + "name": "hdr-exact", + "exact": "exact" + }, + { + "name": "hdr-prefix", + "prefix": "prefix" + }, + { + "name": "hdr-suffix", + "suffix": "suffix" + }, + { + "name": "hdr-regex", + "regex": "regex" + }, + { + "name": "hdr-absent", + "present": true, + "invert": true + } + ] + } + }, + { + "action": "allow", + "http": { + "path_prefix": "/v3/" + } + }, + { + "action": "allow", + "http": { + "path_regex": "/v[12]/.*", + "methods": [ + "GET", + "POST" + ] + } + } + ] + }, + { + "name": "*", + "action": "deny", + "description": "wild desc" + } + ] + } + `, + camelJSON: ` + { + "Kind": "service-intentions", + "Name": "web", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "Sources": [ + { + "Name": "foo", + "Action": "deny", + "Type": "consul", + "Description": "foo desc" + }, + { + "Name": "bar", + "Action": "allow", + "Description": "bar desc" + }, + { + "Name": "l7", + "Permissions": [ + { + "Action": "deny", + "HTTP": { + "PathExact": "/admin", + "Header": [ + { + "Name": "hdr-present", + "Present": true + }, + { + "Name": "hdr-exact", + "Exact": "exact" + }, + { + "Name": "hdr-prefix", + "Prefix": "prefix" + }, + { + "Name": "hdr-suffix", + "Suffix": "suffix" + }, + { + "Name": "hdr-regex", + "Regex": "regex" + }, + { + "Name": "hdr-absent", + "Present": true, + "Invert": true + } + ] + } + }, + { + "Action": "allow", + "HTTP": { + "PathPrefix": "/v3/" + } + }, + { + "Action": "allow", + "HTTP": { + "PathRegex": "/v[12]/.*", + "Methods": [ + "GET", + "POST" + ] + } + } + ] + }, + { + "Name": "*", + "Action": "deny", + "Description": "wild desc" + } + ] + } + `, + expect: &api.ServiceIntentionsConfigEntry{ + Kind: "service-intentions", + Name: "web", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Sources: []*api.SourceIntention{ + { + Name: "foo", + Action: "deny", + Type: "consul", + Description: "foo desc", + }, + { + Name: "bar", + Action: "allow", + Description: "bar desc", + }, + { + Name: "l7", + Permissions: []*api.IntentionPermission{ + { + Action: "deny", + HTTP: &api.IntentionHTTPPermission{ + PathExact: "/admin", + Header: []api.IntentionHTTPHeaderPermission{ + { + Name: "hdr-present", + Present: true, + }, + { + Name: "hdr-exact", + Exact: "exact", + }, + { + Name: "hdr-prefix", + Prefix: "prefix", + }, + { + Name: "hdr-suffix", + Suffix: "suffix", + }, + { + Name: "hdr-regex", + Regex: "regex", + }, + { + Name: "hdr-absent", + Present: true, + Invert: true, + }, + }, + }, + }, + { + Action: "allow", + HTTP: &api.IntentionHTTPPermission{ + PathPrefix: "/v3/", + }, + }, + { + Action: "allow", + HTTP: &api.IntentionHTTPPermission{ + PathRegex: "/v[12]/.*", + Methods: []string{"GET", "POST"}, + }, + }, + }, + }, + { + Name: "*", + Action: "deny", + Description: "wild desc", + }, + }, + }, + }, + { + name: "service-intentions: wildcard destination", + snake: ` + kind = "service-intentions" + name = "*" + sources { + name = "foo" + action = "deny" + # should be parsed, but we'll ignore it later + precedence = 6 + } + `, + camel: ` + Kind = "service-intentions" + Name = "*" + Sources { + Name = "foo" + Action = "deny" + # should be parsed, but we'll ignore it later + Precedence = 6 + } + `, + snakeJSON: ` + { + "kind": "service-intentions", + "name": "*", + "sources": [ + { + "name": "foo", + "action": "deny", + "precedence": 6 + } + ] + } + `, + camelJSON: ` + { + "Kind": "service-intentions", + "Name": "*", + "Sources": [ + { + "Name": "foo", + "Action": "deny", + "Precedence": 6 + } + ] + } + `, + expect: &api.ServiceIntentionsConfigEntry{ + Kind: "service-intentions", + Name: "*", + Sources: []*api.SourceIntention{ + { + Name: "foo", + Action: "deny", + Precedence: 6, + }, + }, + }, + }, + { + name: "mesh", + snake: ` + kind = "mesh" + meta { + "foo" = "bar" + "gir" = "zim" + } + transparent_proxy { + mesh_destinations_only = true + } + tls { + incoming { + tls_min_version = "TLSv1_1" + tls_max_version = "TLSv1_2" + cipher_suites = [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + } + outgoing { + tls_min_version = "TLSv1_1" + tls_max_version = "TLSv1_2" + cipher_suites = [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + } + } + `, + camel: ` + Kind = "mesh" + Meta { + "foo" = "bar" + "gir" = "zim" + } + TransparentProxy { + MeshDestinationsOnly = true + } + TLS { + Incoming { + TLSMinVersion = "TLSv1_1" + TLSMaxVersion = "TLSv1_2" + CipherSuites = [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + } + Outgoing { + TLSMinVersion = "TLSv1_1" + TLSMaxVersion = "TLSv1_2" + CipherSuites = [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + } + } + `, + snakeJSON: ` + { + "kind": "mesh", + "meta" : { + "foo": "bar", + "gir": "zim" + }, + "transparent_proxy": { + "mesh_destinations_only": true + }, + "tls": { + "incoming": { + "tls_min_version": "TLSv1_1", + "tls_max_version": "TLSv1_2", + "cipher_suites": [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + }, + "outgoing": { + "tls_min_version": "TLSv1_1", + "tls_max_version": "TLSv1_2", + "cipher_suites": [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + } + } + } + `, + camelJSON: ` + { + "Kind": "mesh", + "Meta" : { + "foo": "bar", + "gir": "zim" + }, + "TransparentProxy": { + "MeshDestinationsOnly": true + }, + "TLS": { + "Incoming": { + "TLSMinVersion": "TLSv1_1", + "TLSMaxVersion": "TLSv1_2", + "CipherSuites": [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + }, + "Outgoing": { + "TLSMinVersion": "TLSv1_1", + "TLSMaxVersion": "TLSv1_2", + "CipherSuites": [ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" + ] + } + } + } + `, + expect: &api.MeshConfigEntry{ + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + TransparentProxy: api.TransparentProxyMeshConfig{ + MeshDestinationsOnly: true, + }, + TLS: &api.MeshTLSConfig{ + Incoming: &api.MeshDirectionalTLSConfig{ + TLSMinVersion: "TLSv1_1", + TLSMaxVersion: "TLSv1_2", + CipherSuites: []string{ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + }, + }, + Outgoing: &api.MeshDirectionalTLSConfig{ + TLSMinVersion: "TLSv1_1", + TLSMaxVersion: "TLSv1_2", + CipherSuites: []string{ + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", + }, + }, + }, + }, + }, + { + name: "exported-services", + snake: ` + kind = "exported-services" + name = "foo" + meta { + "foo" = "bar" + "gir" = "zim" + } + services = [ + { + name = "web" + namespace = "foo" + consumers = [ + { + partition = "bar" + }, + { + partition = "baz" + }, + { + peer_name = "flarm" + } + ] + }, + { + name = "db" + namespace = "bar" + consumers = [ + { + partition = "zoo" + } + ] + } + ] + `, + camel: ` + Kind = "exported-services" + Name = "foo" + Meta { + "foo" = "bar" + "gir" = "zim" + } + Services = [ + { + Name = "web" + Namespace = "foo" + Consumers = [ + { + Partition = "bar" + }, + { + Partition = "baz" + }, + { + PeerName = "flarm" + } + ] + }, + { + Name = "db" + Namespace = "bar" + Consumers = [ + { + Partition = "zoo" + } + ] + } + ] + `, + snakeJSON: ` + { + "kind": "exported-services", + "name": "foo", + "meta": { + "foo": "bar", + "gir": "zim" + }, + "services": [ + { + "name": "web", + "namespace": "foo", + "consumers": [ + { + "partition": "bar" + }, + { + "partition": "baz" + }, + { + "peer_name": "flarm" + } + ] + }, + { + "name": "db", + "namespace": "bar", + "consumers": [ + { + "partition": "zoo" + } + ] + } + ] + } + `, + camelJSON: ` + { + "Kind": "exported-services", + "Name": "foo", + "Meta": { + "foo": "bar", + "gir": "zim" + }, + "Services": [ + { + "Name": "web", + "Namespace": "foo", + "Consumers": [ + { + "Partition": "bar" + }, + { + "Partition": "baz" + }, + { + "PeerName": "flarm" + } + ] + }, + { + "Name": "db", + "Namespace": "bar", + "Consumers": [ + { + "Partition": "zoo" + } + ] + } + ] + } + `, + expect: &api.ExportedServicesConfigEntry{ + Name: "foo", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + Services: []api.ExportedService{ + { + Name: "web", + Namespace: "foo", + Consumers: []api.ServiceConsumer{ + { + Partition: "bar", + }, + { + Partition: "baz", + }, + { + PeerName: "flarm", + }, + }, + }, + { + Name: "db", + Namespace: "bar", + Consumers: []api.ServiceConsumer{ + { + Partition: "zoo", + }, + }, + }, + }, + }, + }, + } { + tc := tc + + testbody := func(t *testing.T, body string, expect api.ConfigEntry) { + t.Helper() + got, err := ParseConfigEntry(body) + if tc.expectErr != "" { + require.Nil(t, got) + require.Error(t, err) + requireContainsLower(t, err.Error(), tc.expectErr) + } else { + require.NoError(t, err) + require.Equal(t, expect, got) + } + } + + t.Run(tc.name+" (hcl snake case)", func(t *testing.T) { + testbody(t, tc.snake, tc.expect) + }) + t.Run(tc.name+" (hcl camel case)", func(t *testing.T) { + testbody(t, tc.camel, tc.expect) + }) + if tc.snakeJSON != "" { + t.Run(tc.name+" (json snake case)", func(t *testing.T) { + if tc.expectJSON != nil { + testbody(t, tc.snakeJSON, tc.expectJSON) + } else { + testbody(t, tc.snakeJSON, tc.expect) + } + }) + } + if tc.camelJSON != "" { + t.Run(tc.name+" (json camel case)", func(t *testing.T) { + if tc.expectJSON != nil { + testbody(t, tc.camelJSON, tc.expectJSON) + } else { + testbody(t, tc.camelJSON, tc.expect) + } + }) + } + } +} + +func requireContainsLower(t *testing.T, haystack, needle string) { + t.Helper() + require.Contains(t, strings.ToLower(haystack), strings.ToLower(needle)) +} + +func intPointer(v int) *int { + return &v +} diff --git a/docs/rpc/README.md b/docs/rpc/README.md index b10681e8fd..adfa19459f 100644 --- a/docs/rpc/README.md +++ b/docs/rpc/README.md @@ -1,26 +1,26 @@ # RPC -This section is a work in progress. +Consul uses two RPC systems for communication between components within the +cluster and with other clients such as Envoy: [gRPC](https://grpc.io/) +and Go's [`net/rpc`](https://pkg.go.dev/net/rpc) package. -The RPC subsystem is exclusicely in Server Agents. It is comprised of two main components: +Communication between client agents and servers uses a mix of both gRPC and +`net/rpc`. Generally, gRPC is preferred because it supports modern features +such as context deadlines/cancellation, streaming, and middleware - but Consul +has been around for a while so the majority of RPC endpoints still use `net/rpc`. -1. the "RPC Server" (for lack of a better term) handles multiplexing of many different - requests on a single TCP port. -2. RPC endpoints handle RPC requests and return responses. +## Multiplexed "Server" Port -The RPC subsystems handles requests from: +Most in-cluster communication happens over the multiplexed "server" TCP port +(default: 8300). Consul servers implement a custom protocol for serving +different kinds of traffic on the same port, whereby the first byte sent +indicates the protocol (e.g. gRPC, `net/rpc`, Raft). -1. Client Agents in the local DC -2. (if the server is a leader) other Server Agents in the local DC -3. Server Agents in other Datacenters -4. in-process requests from other components running in the same process (ex: the HTTP API - or DNS interface). +Servers also implement [TLS ALPN](https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation) +on this port, for situations where wrapping the real protocol with a byte prefix +isn't practical (e.g. cross-DC traffic over mesh gateways). -## Routing - -The "RPC Server" accepts requests to the [server port] and routes the requests based on -configuration of the Server and the the first byte in the request. The diagram below shows -all the possible routing flows. +The diagram below shows all the possible routing flows: [server port]: https://www.consul.io/docs/agent/config/config-files#server_rpc_port @@ -28,11 +28,10 @@ all the possible routing flows. [source](./routing.mmd) -The main entrypoint to RPC routing is `handleConn` in [agent/consul/rpc.go]. +The main entrypoint to connection routing is `handleConn` in [agent/consul/rpc.go]. [agent/consul/rpc.go]: https://github.com/hashicorp/consul/blob/main/agent/consul/rpc.go - ### Development Multiplexing several protocols over a single server port helps to reduce our @@ -44,13 +43,35 @@ development tools such as [grpcurl] difficult. You can get a "plain" TCP connection to the gRPC server using this proxy script: ``` -$ go run tools/private-grpc-proxy/main.go localhost:8300 -Proxying connections to Consul's private gRPC server +$ go run tools/internal-grpc-proxy/main.go localhost:8300 +Proxying connections to Consul's internal gRPC server Use this address: 127.0.0.1:64077 ``` Pass the returned proxy address to your tool of choice. +## Private vs Public vs Internal vs External +When working on Consul's gRPC endpoints you may notice we use private/public and +internal/external slightly differently. + +Private and public refer to whether an API is suitable for consumption by +clients other than Consul's core components. + +Private gRPC APIs are defined in the `proto` directory, and should only be used +by Consul servers and agents. Public gRPC APIs are defined in the `proto-public` +directory and may be used by 3rd-party applications. + +Internal and external refer to how the gRPC APIs are exposed. + +Internal gRPC APIs are exposed on the multiplexed "server" port, whereas +external APIs are exposed on a dedicated gRPC port (default: 8502). + +The reason for this differentiation is that some private APIs are exposed on the +external port, such as peer streaming/replication; this API isn't (yet) suitable +for consumption by 3rd-party applications but must be accessible from outside +the cluster, and present a TLS certificate signed by a public CA, which the +multiplexed port cannot. + ## RPC Endpoints This section is a work in progress, it will eventually cover topics like: diff --git a/docs/rpc/streaming/README.md b/docs/rpc/streaming/README.md index 3cd2ca6feb..dd6873cde8 100644 --- a/docs/rpc/streaming/README.md +++ b/docs/rpc/streaming/README.md @@ -34,7 +34,7 @@ and sent to any active subscriptions. [rpcclient/health.Health]: https://github.com/hashicorp/consul/blob/main/agent/rpcclient/health/health.go [StreamingHealthServices cache-type]: https://github.com/hashicorp/consul/blob/main/agent/cache-types/streaming_health_services.go [materialized view]: https://github.com/hashicorp/consul/blob/main/agent/submatview/materializer.go -[SubscribeEndpoint]: https://github.com/hashicorp/consul/blob/main/agent/grpc/private/services/subscribe/subscribe.go +[SubscribeEndpoint]: https://github.com/hashicorp/consul/blob/main/agent/grpc-internal/services/subscribe/subscribe.go [EventPublisher]: https://github.com/hashicorp/consul/blob/main/agent/consul/stream/event_publisher.go [state.Store commits]: https://github.com/hashicorp/consul/blob/main/agent/consul/state/memdb.go diff --git a/proto/pbacl/acl.pb.go b/proto/pbacl/acl.pb.go index 435a298b02..ede3fc3ba4 100644 --- a/proto/pbacl/acl.pb.go +++ b/proto/pbacl/acl.pb.go @@ -80,17 +80,27 @@ var File_proto_pbacl_acl_proto protoreflect.FileDescriptor var file_proto_pbacl_acl_proto_rawDesc = []byte{ 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x61, 0x63, 0x6c, 0x2f, 0x61, 0x63, - 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x61, 0x63, 0x6c, 0x22, 0x2d, 0x0a, 0x07, - 0x41, 0x43, 0x4c, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0x68, 0x0a, 0x07, 0x63, - 0x6f, 0x6d, 0x2e, 0x61, 0x63, 0x6c, 0x42, 0x08, 0x41, 0x63, 0x6c, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x27, 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, 0x61, 0x63, 0x6c, 0xa2, 0x02, 0x03, 0x41, 0x58, - 0x58, 0xaa, 0x02, 0x03, 0x41, 0x63, 0x6c, 0xca, 0x02, 0x03, 0x41, 0x63, 0x6c, 0xe2, 0x02, 0x0f, - 0x41, 0x63, 0x6c, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x03, 0x41, 0x63, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1d, 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, 0x61, 0x63, 0x6c, 0x22, 0x2d, 0x0a, 0x07, 0x41, 0x43, 0x4c, 0x4c, 0x69, 0x6e, + 0x6b, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, + 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x42, 0xee, 0x01, 0x0a, 0x21, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x61, 0x63, 0x6c, 0x42, 0x08, 0x41, 0x63, 0x6c, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x27, 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, 0x61, 0x63, 0x6c, + 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x41, 0xaa, 0x02, 0x1d, 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, 0x41, 0x63, 0x6c, 0xca, 0x02, 0x1d, 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, 0x41, 0x63, 0x6c, 0xe2, 0x02, 0x29, 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, 0x41, 0x63, 0x6c, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x20, 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, 0x41, 0x63, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -107,7 +117,7 @@ func file_proto_pbacl_acl_proto_rawDescGZIP() []byte { var file_proto_pbacl_acl_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_proto_pbacl_acl_proto_goTypes = []interface{}{ - (*ACLLink)(nil), // 0: acl.ACLLink + (*ACLLink)(nil), // 0: hashicorp.consul.internal.acl.ACLLink } var file_proto_pbacl_acl_proto_depIdxs = []int32{ 0, // [0:0] is the sub-list for method output_type diff --git a/proto/pbacl/acl.proto b/proto/pbacl/acl.proto index 252d7bb51c..299149c2e0 100644 --- a/proto/pbacl/acl.proto +++ b/proto/pbacl/acl.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package acl; +package hashicorp.consul.internal.acl; message ACLLink { string ID = 1; diff --git a/proto/pbautoconf/auto_config.pb.go b/proto/pbautoconf/auto_config.pb.go index 41d2901e64..f93a4263d6 100644 --- a/proto/pbautoconf/auto_config.pb.go +++ b/proto/pbautoconf/auto_config.pb.go @@ -214,46 +214,61 @@ var File_proto_pbautoconf_auto_config_proto protoreflect.FileDescriptor var file_proto_pbautoconf_auto_config_proto_rawDesc = []byte{ 0x0a, 0x22, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0x1a, 0x1b, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc5, 0x01, 0x0a, 0x11, 0x41, - 0x75, 0x74, 0x6f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1c, - 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, - 0x4a, 0x57, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x12, 0x20, - 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x12, 0x10, 0x0a, 0x03, 0x43, 0x53, 0x52, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x43, - 0x53, 0x52, 0x22, 0xd1, 0x01, 0x0a, 0x12, 0x41, 0x75, 0x74, 0x6f, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x06, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x2a, 0x0a, 0x07, 0x43, 0x41, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x43, 0x41, 0x52, - 0x6f, 0x6f, 0x74, 0x73, 0x52, 0x07, 0x43, 0x41, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x35, 0x0a, - 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x49, 0x73, 0x73, - 0x75, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x52, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x43, 0x41, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, 0x43, 0x41, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x42, 0x8d, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x61, - 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0x42, 0x0f, 0x41, 0x75, 0x74, 0x6f, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 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, - 0x61, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0xa2, 0x02, 0x03, 0x41, 0x58, 0x58, 0xaa, 0x02, - 0x08, 0x41, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0xca, 0x02, 0x08, 0x41, 0x75, 0x74, 0x6f, - 0x63, 0x6f, 0x6e, 0x66, 0xe2, 0x02, 0x14, 0x41, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x08, 0x41, 0x75, - 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x22, 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, + 0x61, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, + 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc5, 0x01, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x6f, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, + 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x6f, + 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x4a, 0x57, 0x54, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x4a, 0x57, 0x54, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x43, 0x53, + 0x52, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x43, 0x53, 0x52, 0x22, 0x9f, 0x02, 0x0a, + 0x12, 0x41, 0x75, 0x74, 0x6f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x28, 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, 0x66, 0x69, 0x67, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x44, 0x0a, 0x07, 0x43, 0x41, 0x52, 0x6f, 0x6f, 0x74, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x43, 0x41, 0x52, 0x6f, 0x6f, + 0x74, 0x73, 0x52, 0x07, 0x43, 0x41, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x4f, 0x0a, 0x0b, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2d, 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, + 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x52, + 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x30, 0x0a, 0x13, + 0x45, 0x78, 0x74, 0x72, 0x61, 0x43, 0x41, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x45, 0x78, 0x74, 0x72, 0x61, + 0x43, 0x41, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x42, 0x93, + 0x02, 0x0a, 0x26, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0x42, 0x0f, 0x41, 0x75, 0x74, 0x6f, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2c, 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, 0x61, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, + 0x41, 0xaa, 0x02, 0x22, 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, 0x41, 0x75, + 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0xca, 0x02, 0x22, 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, 0x41, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, 0xe2, 0x02, 0x2e, 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, 0x41, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6e, 0x66, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x25, 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, 0x41, 0x75, 0x74, 0x6f, + 0x63, 0x6f, 0x6e, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -270,16 +285,16 @@ func file_proto_pbautoconf_auto_config_proto_rawDescGZIP() []byte { var file_proto_pbautoconf_auto_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_proto_pbautoconf_auto_config_proto_goTypes = []interface{}{ - (*AutoConfigRequest)(nil), // 0: autoconf.AutoConfigRequest - (*AutoConfigResponse)(nil), // 1: autoconf.AutoConfigResponse - (*pbconfig.Config)(nil), // 2: config.Config - (*pbconnect.CARoots)(nil), // 3: connect.CARoots - (*pbconnect.IssuedCert)(nil), // 4: connect.IssuedCert + (*AutoConfigRequest)(nil), // 0: hashicorp.consul.internal.autoconf.AutoConfigRequest + (*AutoConfigResponse)(nil), // 1: hashicorp.consul.internal.autoconf.AutoConfigResponse + (*pbconfig.Config)(nil), // 2: hashicorp.consul.internal.config.Config + (*pbconnect.CARoots)(nil), // 3: hashicorp.consul.internal.connect.CARoots + (*pbconnect.IssuedCert)(nil), // 4: hashicorp.consul.internal.connect.IssuedCert } var file_proto_pbautoconf_auto_config_proto_depIdxs = []int32{ - 2, // 0: autoconf.AutoConfigResponse.Config:type_name -> config.Config - 3, // 1: autoconf.AutoConfigResponse.CARoots:type_name -> connect.CARoots - 4, // 2: autoconf.AutoConfigResponse.Certificate:type_name -> connect.IssuedCert + 2, // 0: hashicorp.consul.internal.autoconf.AutoConfigResponse.Config:type_name -> hashicorp.consul.internal.config.Config + 3, // 1: hashicorp.consul.internal.autoconf.AutoConfigResponse.CARoots:type_name -> hashicorp.consul.internal.connect.CARoots + 4, // 2: hashicorp.consul.internal.autoconf.AutoConfigResponse.Certificate:type_name -> hashicorp.consul.internal.connect.IssuedCert 3, // [3:3] is the sub-list for method output_type 3, // [3:3] is the sub-list for method input_type 3, // [3:3] is the sub-list for extension type_name diff --git a/proto/pbautoconf/auto_config.proto b/proto/pbautoconf/auto_config.proto index fc8d3cdefb..c43f1c912e 100644 --- a/proto/pbautoconf/auto_config.proto +++ b/proto/pbautoconf/auto_config.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package autoconf; +package hashicorp.consul.internal.autoconf; import "proto/pbconfig/config.proto"; import "proto/pbconnect/connect.proto"; diff --git a/proto/pbcommon/common.pb.go b/proto/pbcommon/common.pb.go index 7ccab87394..80010a7ab0 100644 --- a/proto/pbcommon/common.pb.go +++ b/proto/pbcommon/common.pb.go @@ -594,85 +594,95 @@ var File_proto_pbcommon_common_proto protoreflect.FileDescriptor var file_proto_pbcommon_common_proto_rawDesc = []byte{ 0x0a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4f, 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, 0x6e, - 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, - 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x32, 0x0a, 0x10, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x24, 0x0a, 0x0c, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x22, 0x51, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x11, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x74, 0x22, 0xec, 0x03, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x4d, 0x69, - 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0d, 0x4d, 0x69, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x12, 0x3d, 0x0a, 0x0c, 0x4d, 0x61, 0x78, 0x51, 0x75, 0x65, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0c, 0x4d, 0x61, 0x78, 0x51, 0x75, 0x65, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x1e, 0x0a, 0x0a, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0a, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x12, + 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x1a, + 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, + 0x4f, 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0b, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, + 0x0a, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x22, 0x32, 0x0a, 0x10, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x22, 0x24, 0x0a, 0x0c, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x51, 0x0a, 0x0b, 0x52, 0x65, + 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x52, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x55, 0x73, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x08, 0x55, 0x73, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x4d, 0x61, 0x78, - 0x53, 0x74, 0x61, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, - 0x4d, 0x61, 0x78, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x31, 0x0a, 0x06, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x52, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x22, 0xec, 0x03, + 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x14, + 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x4d, 0x69, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x4d, 0x69, 0x6e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x3d, 0x0a, 0x0c, 0x4d, 0x61, + 0x78, 0x51, 0x75, 0x65, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x4d, 0x61, 0x78, - 0x41, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x4d, 0x75, 0x73, 0x74, 0x52, 0x65, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x61, 0x74, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x4d, 0x75, 0x73, - 0x74, 0x52, 0x65, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x53, - 0x74, 0x61, 0x6c, 0x65, 0x49, 0x66, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x53, 0x74, - 0x61, 0x6c, 0x65, 0x49, 0x66, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x22, 0xee, 0x01, 0x0a, 0x09, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x61, - 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x3b, 0x0a, 0x0b, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, + 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x4d, 0x61, 0x78, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x41, 0x6c, 0x6c, + 0x6f, 0x77, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x41, + 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x52, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x43, 0x6f, 0x6e, + 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x55, 0x73, 0x65, 0x43, 0x61, + 0x63, 0x68, 0x65, 0x12, 0x45, 0x0a, 0x10, 0x4d, 0x61, 0x78, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x44, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x4d, 0x61, 0x78, 0x53, 0x74, 0x61, + 0x6c, 0x65, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x06, 0x4d, 0x61, + 0x78, 0x41, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x12, 0x26, 0x0a, + 0x0e, 0x4d, 0x75, 0x73, 0x74, 0x52, 0x65, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x4d, 0x75, 0x73, 0x74, 0x52, 0x65, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x49, 0x66, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x4c, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x4c, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x10, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, - 0x6c, 0x12, 0x34, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x65, 0x64, 0x42, 0x79, 0x41, 0x43, 0x4c, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x15, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, - 0x64, 0x42, 0x79, 0x41, 0x43, 0x4c, 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, - 0x06, 0x10, 0x07, 0x22, 0x4c, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x7d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x42, - 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2a, - 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, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, - 0xaa, 0x02, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0xca, 0x02, 0x06, 0x43, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0xe2, 0x02, 0x12, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x49, 0x66, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x0b, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0xee, 0x01, 0x0a, + 0x09, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x3b, 0x0a, 0x0b, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0b, 0x4c, 0x61, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x12, 0x20, 0x0a, + 0x0b, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0b, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, + 0x2a, 0x0a, 0x10, 0x43, 0x6f, 0x6e, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, + 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x43, 0x6f, 0x6e, 0x73, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x34, 0x0a, 0x15, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x42, 0x79, + 0x41, 0x43, 0x4c, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x65, 0x64, 0x42, 0x79, 0x41, 0x43, 0x4c, + 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x4c, 0x0a, + 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, + 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, + 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x83, 0x02, 0x0a, 0x24, + 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x42, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x50, 0x01, 0x5a, 0x2a, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0xa2, + 0x02, 0x04, 0x48, 0x43, 0x49, 0x43, 0xaa, 0x02, 0x20, 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, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0xca, 0x02, 0x20, 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, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0xe2, 0x02, 0x2c, 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, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x23, 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, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -689,21 +699,21 @@ func file_proto_pbcommon_common_proto_rawDescGZIP() []byte { var file_proto_pbcommon_common_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_proto_pbcommon_common_proto_goTypes = []interface{}{ - (*RaftIndex)(nil), // 0: common.RaftIndex - (*TargetDatacenter)(nil), // 1: common.TargetDatacenter - (*WriteRequest)(nil), // 2: common.WriteRequest - (*ReadRequest)(nil), // 3: common.ReadRequest - (*QueryOptions)(nil), // 4: common.QueryOptions - (*QueryMeta)(nil), // 5: common.QueryMeta - (*EnterpriseMeta)(nil), // 6: common.EnterpriseMeta + (*RaftIndex)(nil), // 0: hashicorp.consul.internal.common.RaftIndex + (*TargetDatacenter)(nil), // 1: hashicorp.consul.internal.common.TargetDatacenter + (*WriteRequest)(nil), // 2: hashicorp.consul.internal.common.WriteRequest + (*ReadRequest)(nil), // 3: hashicorp.consul.internal.common.ReadRequest + (*QueryOptions)(nil), // 4: hashicorp.consul.internal.common.QueryOptions + (*QueryMeta)(nil), // 5: hashicorp.consul.internal.common.QueryMeta + (*EnterpriseMeta)(nil), // 6: hashicorp.consul.internal.common.EnterpriseMeta (*durationpb.Duration)(nil), // 7: google.protobuf.Duration } var file_proto_pbcommon_common_proto_depIdxs = []int32{ - 7, // 0: common.QueryOptions.MaxQueryTime:type_name -> google.protobuf.Duration - 7, // 1: common.QueryOptions.MaxStaleDuration:type_name -> google.protobuf.Duration - 7, // 2: common.QueryOptions.MaxAge:type_name -> google.protobuf.Duration - 7, // 3: common.QueryOptions.StaleIfError:type_name -> google.protobuf.Duration - 7, // 4: common.QueryMeta.LastContact:type_name -> google.protobuf.Duration + 7, // 0: hashicorp.consul.internal.common.QueryOptions.MaxQueryTime:type_name -> google.protobuf.Duration + 7, // 1: hashicorp.consul.internal.common.QueryOptions.MaxStaleDuration:type_name -> google.protobuf.Duration + 7, // 2: hashicorp.consul.internal.common.QueryOptions.MaxAge:type_name -> google.protobuf.Duration + 7, // 3: hashicorp.consul.internal.common.QueryOptions.StaleIfError:type_name -> google.protobuf.Duration + 7, // 4: hashicorp.consul.internal.common.QueryMeta.LastContact:type_name -> google.protobuf.Duration 5, // [5:5] is the sub-list for method output_type 5, // [5:5] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name diff --git a/proto/pbcommon/common.proto b/proto/pbcommon/common.proto index b4b47099e8..1c6d9f2608 100644 --- a/proto/pbcommon/common.proto +++ b/proto/pbcommon/common.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package common; +package hashicorp.consul.internal.common; import "google/protobuf/duration.proto"; diff --git a/proto/pbconfig/config.pb.go b/proto/pbconfig/config.pb.go index aea729fe32..80953c882b 100644 --- a/proto/pbconfig/config.pb.go +++ b/proto/pbconfig/config.pb.go @@ -682,124 +682,145 @@ var File_proto_pbconfig_config_proto protoreflect.FileDescriptor var file_proto_pbconfig_config_proto_rawDesc = []byte{ 0x0a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xcf, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x12, 0x2c, 0x0a, 0x11, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61, 0x63, - 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x50, 0x72, 0x69, - 0x6d, 0x61, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1a, - 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, - 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, - 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x03, 0x41, 0x43, - 0x4c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2e, 0x41, 0x43, 0x4c, 0x52, 0x03, 0x41, 0x43, 0x4c, 0x12, 0x35, 0x0a, 0x0b, 0x41, 0x75, 0x74, - 0x6f, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x45, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x52, 0x0b, 0x41, 0x75, 0x74, 0x6f, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x12, 0x26, 0x0a, 0x06, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0e, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, - 0x52, 0x06, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x12, 0x1d, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, - 0x4c, 0x53, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x22, 0x66, 0x0a, 0x06, 0x47, 0x6f, 0x73, 0x73, 0x69, - 0x70, 0x12, 0x38, 0x0a, 0x0a, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x47, - 0x6f, 0x73, 0x73, 0x69, 0x70, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0a, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x52, - 0x65, 0x74, 0x72, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x4c, 0x41, 0x4e, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0c, 0x52, 0x65, 0x74, 0x72, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x4c, 0x41, 0x4e, 0x22, - 0x74, 0x0a, 0x10, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x49, - 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x56, - 0x65, 0x72, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x26, 0x0a, - 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4f, 0x75, 0x74, - 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x22, 0xfa, 0x01, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x26, 0x0a, - 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4f, 0x75, 0x74, - 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x0a, 0x14, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x14, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, - 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, - 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x53, 0x0a, - 0x23, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x50, 0x72, 0x65, 0x66, - 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, - 0x69, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x22, - 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, - 0x65, 0x73, 0x22, 0xbb, 0x03, 0x0a, 0x03, 0x41, 0x43, 0x4c, 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x54, - 0x4c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, - 0x54, 0x4c, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x54, 0x4c, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x54, 0x4c, 0x12, 0x1a, 0x0a, 0x08, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x54, 0x54, 0x4c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x54, 0x54, 0x4c, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x6f, 0x77, 0x6e, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x6f, - 0x77, 0x6e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x30, - 0x0a, 0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x12, 0x29, 0x0a, 0x06, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x41, 0x43, 0x4c, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x73, 0x52, 0x06, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x39, 0x0a, 0x16, 0x44, - 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, - 0x15, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x12, 0x36, 0x0a, 0x16, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x30, - 0x0a, 0x13, 0x4d, 0x53, 0x50, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6f, 0x6f, 0x74, - 0x73, 0x74, 0x72, 0x61, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x4d, 0x53, 0x50, - 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, - 0x22, 0x8a, 0x02, 0x0a, 0x09, 0x41, 0x43, 0x4c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x2c, - 0x0a, 0x11, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x49, 0x6e, 0x69, 0x74, 0x69, - 0x61, 0x6c, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, - 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, - 0x0a, 0x0d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x14, - 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x12, 0x57, 0x0a, 0x16, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x41, 0x43, - 0x4c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x16, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x22, 0x55, 0x0a, - 0x17, 0x41, 0x43, 0x4c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x6f, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x53, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x49, 0x44, 0x22, 0x69, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x6f, 0x45, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x16, 0x0a, 0x06, 0x44, 0x4e, 0x53, 0x53, 0x41, 0x4e, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x44, 0x4e, 0x53, 0x53, 0x41, 0x4e, 0x12, 0x14, 0x0a, - 0x05, 0x49, 0x50, 0x53, 0x41, 0x4e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x49, 0x50, - 0x53, 0x41, 0x4e, 0x12, 0x1a, 0x0a, 0x08, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x54, 0x4c, 0x53, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x54, 0x4c, 0x53, 0x42, - 0x7d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0b, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2a, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, - 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0xca, 0x02, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0xe2, 0x02, 0x12, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 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, 0x66, 0x69, 0x67, 0x22, + 0xb7, 0x03, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, + 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x11, 0x50, 0x72, + 0x69, 0x6d, 0x61, 0x72, 0x79, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x44, 0x61, + 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x4e, 0x6f, 0x64, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x4e, + 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x65, 0x67, 0x6d, 0x65, + 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x03, 0x41, 0x43, 0x4c, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x25, 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, 0x66, 0x69, 0x67, 0x2e, 0x41, 0x43, 0x4c, 0x52, 0x03, 0x41, 0x43, 0x4c, 0x12, 0x4f, 0x0a, + 0x0b, 0x41, 0x75, 0x74, 0x6f, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2d, 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, 0x66, 0x69, 0x67, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, + 0x74, 0x52, 0x0b, 0x41, 0x75, 0x74, 0x6f, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x12, 0x40, + 0x0a, 0x06, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, + 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, 0x66, 0x69, + 0x67, 0x2e, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x52, 0x06, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, + 0x12, 0x37, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 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, 0x66, 0x69, 0x67, + 0x2e, 0x54, 0x4c, 0x53, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x22, 0x80, 0x01, 0x0a, 0x06, 0x47, 0x6f, + 0x73, 0x73, 0x69, 0x70, 0x12, 0x52, 0x0a, 0x0a, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 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, 0x66, 0x69, 0x67, 0x2e, 0x47, 0x6f, 0x73, 0x73, + 0x69, 0x70, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x45, 0x6e, + 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x52, 0x65, 0x74, 0x72, + 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x4c, 0x41, 0x4e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, + 0x52, 0x65, 0x74, 0x72, 0x79, 0x4a, 0x6f, 0x69, 0x6e, 0x4c, 0x41, 0x4e, 0x22, 0x74, 0x0a, 0x10, + 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4b, + 0x65, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x63, 0x6f, + 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x56, 0x65, 0x72, 0x69, + 0x66, 0x79, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x26, 0x0a, 0x0e, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, + 0x6e, 0x67, 0x22, 0xfa, 0x01, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x26, 0x0a, 0x0e, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, + 0x6e, 0x67, 0x12, 0x32, 0x0a, 0x14, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x14, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x48, 0x6f, + 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, + 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, + 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x69, + 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x23, 0x44, 0x65, + 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, + 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x22, 0x44, 0x65, 0x70, + 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x53, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, + 0xd5, 0x03, 0x0a, 0x03, 0x41, 0x43, 0x4c, 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x54, 0x4c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x54, 0x54, 0x4c, 0x12, + 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x54, 0x4c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x52, 0x6f, 0x6c, 0x65, 0x54, 0x54, 0x4c, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x54, 0x54, 0x4c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x54, 0x54, 0x4c, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x6f, 0x77, 0x6e, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x6f, 0x77, 0x6e, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x44, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x4b, 0x65, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x43, 0x0a, + 0x06, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, 0x66, 0x69, 0x67, + 0x2e, 0x41, 0x43, 0x4c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x52, 0x06, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x73, 0x12, 0x39, 0x0a, 0x16, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x15, 0x44, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, + 0x65, 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x12, 0x36, 0x0a, + 0x16, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x50, 0x65, 0x72, 0x73, + 0x69, 0x73, 0x74, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x50, 0x65, 0x72, 0x73, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x4d, 0x53, 0x50, 0x44, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x13, 0x4d, 0x53, 0x50, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x6f, + 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x22, 0xa4, 0x02, 0x0a, 0x09, 0x41, 0x43, 0x4c, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, + 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x11, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x41, 0x67, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x44, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x44, 0x65, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x71, 0x0a, 0x16, 0x4d, + 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x41, + 0x43, 0x4c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x16, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x22, 0x55, + 0x0a, 0x17, 0x41, 0x43, 0x4c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x6f, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x53, 0x65, 0x63, + 0x72, 0x65, 0x74, 0x49, 0x44, 0x22, 0x69, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x6f, 0x45, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x16, 0x0a, 0x06, 0x44, 0x4e, 0x53, 0x53, 0x41, 0x4e, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x44, 0x4e, 0x53, 0x53, 0x41, 0x4e, 0x12, 0x14, + 0x0a, 0x05, 0x49, 0x50, 0x53, 0x41, 0x4e, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x49, + 0x50, 0x53, 0x41, 0x4e, 0x12, 0x1a, 0x0a, 0x08, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x54, 0x4c, 0x53, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x54, 0x4c, 0x53, + 0x42, 0x83, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2a, 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, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x43, 0xaa, 0x02, 0x20, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0xca, 0x02, + 0x20, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0xe2, 0x02, 0x2c, 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, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x23, 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, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -816,23 +837,23 @@ func file_proto_pbconfig_config_proto_rawDescGZIP() []byte { var file_proto_pbconfig_config_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_proto_pbconfig_config_proto_goTypes = []interface{}{ - (*Config)(nil), // 0: config.Config - (*Gossip)(nil), // 1: config.Gossip - (*GossipEncryption)(nil), // 2: config.GossipEncryption - (*TLS)(nil), // 3: config.TLS - (*ACL)(nil), // 4: config.ACL - (*ACLTokens)(nil), // 5: config.ACLTokens - (*ACLServiceProviderToken)(nil), // 6: config.ACLServiceProviderToken - (*AutoEncrypt)(nil), // 7: config.AutoEncrypt + (*Config)(nil), // 0: hashicorp.consul.internal.config.Config + (*Gossip)(nil), // 1: hashicorp.consul.internal.config.Gossip + (*GossipEncryption)(nil), // 2: hashicorp.consul.internal.config.GossipEncryption + (*TLS)(nil), // 3: hashicorp.consul.internal.config.TLS + (*ACL)(nil), // 4: hashicorp.consul.internal.config.ACL + (*ACLTokens)(nil), // 5: hashicorp.consul.internal.config.ACLTokens + (*ACLServiceProviderToken)(nil), // 6: hashicorp.consul.internal.config.ACLServiceProviderToken + (*AutoEncrypt)(nil), // 7: hashicorp.consul.internal.config.AutoEncrypt } var file_proto_pbconfig_config_proto_depIdxs = []int32{ - 4, // 0: config.Config.ACL:type_name -> config.ACL - 7, // 1: config.Config.AutoEncrypt:type_name -> config.AutoEncrypt - 1, // 2: config.Config.Gossip:type_name -> config.Gossip - 3, // 3: config.Config.TLS:type_name -> config.TLS - 2, // 4: config.Gossip.Encryption:type_name -> config.GossipEncryption - 5, // 5: config.ACL.Tokens:type_name -> config.ACLTokens - 6, // 6: config.ACLTokens.ManagedServiceProvider:type_name -> config.ACLServiceProviderToken + 4, // 0: hashicorp.consul.internal.config.Config.ACL:type_name -> hashicorp.consul.internal.config.ACL + 7, // 1: hashicorp.consul.internal.config.Config.AutoEncrypt:type_name -> hashicorp.consul.internal.config.AutoEncrypt + 1, // 2: hashicorp.consul.internal.config.Config.Gossip:type_name -> hashicorp.consul.internal.config.Gossip + 3, // 3: hashicorp.consul.internal.config.Config.TLS:type_name -> hashicorp.consul.internal.config.TLS + 2, // 4: hashicorp.consul.internal.config.Gossip.Encryption:type_name -> hashicorp.consul.internal.config.GossipEncryption + 5, // 5: hashicorp.consul.internal.config.ACL.Tokens:type_name -> hashicorp.consul.internal.config.ACLTokens + 6, // 6: hashicorp.consul.internal.config.ACLTokens.ManagedServiceProvider:type_name -> hashicorp.consul.internal.config.ACLServiceProviderToken 7, // [7:7] is the sub-list for method output_type 7, // [7:7] is the sub-list for method input_type 7, // [7:7] is the sub-list for extension type_name diff --git a/proto/pbconfig/config.proto b/proto/pbconfig/config.proto index eb54e7d435..749bc65e5c 100644 --- a/proto/pbconfig/config.proto +++ b/proto/pbconfig/config.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package config; +package hashicorp.consul.internal.config; message Config { string Datacenter = 1; diff --git a/proto/pbconfigentry/config_entry.pb.go b/proto/pbconfigentry/config_entry.pb.go index 43ae89f6a4..9a34e8248c 100644 --- a/proto/pbconfigentry/config_entry.pb.go +++ b/proto/pbconfigentry/config_entry.pb.go @@ -172,7 +172,7 @@ type ConfigEntry struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Kind Kind `protobuf:"varint,1,opt,name=Kind,proto3,enum=configentry.Kind" json:"Kind,omitempty"` + Kind Kind `protobuf:"varint,1,opt,name=Kind,proto3,enum=hashicorp.consul.internal.configentry.Kind" json:"Kind,omitempty"` Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,3,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` RaftIndex *pbcommon.RaftIndex `protobuf:"bytes,4,opt,name=RaftIndex,proto3" json:"RaftIndex,omitempty"` @@ -1869,13 +1869,13 @@ type SourceIntention struct { Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` // mog: func-to=intentionActionToStructs func-from=intentionActionFromStructs - Action IntentionAction `protobuf:"varint,2,opt,name=Action,proto3,enum=configentry.IntentionAction" json:"Action,omitempty"` + Action IntentionAction `protobuf:"varint,2,opt,name=Action,proto3,enum=hashicorp.consul.internal.configentry.IntentionAction" json:"Action,omitempty"` Permissions []*IntentionPermission `protobuf:"bytes,3,rep,name=Permissions,proto3" json:"Permissions,omitempty"` // mog: func-to=int func-from=int32 Precedence int32 `protobuf:"varint,4,opt,name=Precedence,proto3" json:"Precedence,omitempty"` LegacyID string `protobuf:"bytes,5,opt,name=LegacyID,proto3" json:"LegacyID,omitempty"` // mog: func-to=intentionSourceTypeToStructs func-from=intentionSourceTypeFromStructs - Type IntentionSourceType `protobuf:"varint,6,opt,name=Type,proto3,enum=configentry.IntentionSourceType" json:"Type,omitempty"` + Type IntentionSourceType `protobuf:"varint,6,opt,name=Type,proto3,enum=hashicorp.consul.internal.configentry.IntentionSourceType" json:"Type,omitempty"` Description string `protobuf:"bytes,7,opt,name=Description,proto3" json:"Description,omitempty"` LegacyMeta map[string]string `protobuf:"bytes,8,rep,name=LegacyMeta,proto3" json:"LegacyMeta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // mog: func-to=timeToStructs func-from=timeFromStructs @@ -2014,7 +2014,7 @@ type IntentionPermission struct { unknownFields protoimpl.UnknownFields // mog: func-to=intentionActionToStructs func-from=intentionActionFromStructs - Action IntentionAction `protobuf:"varint,1,opt,name=Action,proto3,enum=configentry.IntentionAction" json:"Action,omitempty"` + Action IntentionAction `protobuf:"varint,1,opt,name=Action,proto3,enum=hashicorp.consul.internal.configentry.IntentionAction" json:"Action,omitempty"` HTTP *IntentionHTTPPermission `protobuf:"bytes,2,opt,name=HTTP,proto3" json:"HTTP,omitempty"` } @@ -2253,176 +2253,215 @@ var File_proto_pbconfigentry_config_entry_proto protoreflect.FileDescriptor var file_proto_pbconfigentry_config_entry_proto_rawDesc = []byte{ 0x0a, 0x26, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0xde, 0x03, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x12, 0x25, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3e, - 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, - 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2f, - 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, - 0x39, 0x0a, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0a, - 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x48, 0x0a, 0x0f, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, - 0x72, 0x48, 0x00, 0x52, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x12, 0x45, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, - 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, - 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x48, 0x00, 0x52, 0x0e, 0x49, 0x6e, 0x67, - 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4e, 0x0a, 0x11, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x1a, + 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x94, 0x05, + 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x3f, 0x0a, + 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x49, 0x0a, 0x09, + 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2b, 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, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, + 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x53, 0x0a, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, + 0x52, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x62, 0x0a, 0x0f, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x48, 0x00, 0x52, + 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, + 0x12, 0x5f, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x18, 0x07, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x48, + 0x00, 0x52, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x12, 0x68, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x48, 0x00, 0x52, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x07, 0x0a, 0x05, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x22, 0xb0, 0x02, 0x0a, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x53, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x65, 0x73, 0x68, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, - 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x2c, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x2f, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x35, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x50, 0x0a, 0x1a, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x65, 0x73, 0x68, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x14, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x95, 0x01, 0x0a, 0x0d, 0x4d, 0x65, - 0x73, 0x68, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x41, 0x0a, 0x08, 0x49, - 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x6e, 0x74, 0x72, 0x79, 0x22, 0x98, 0x03, 0x0a, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x6d, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x01, 0x20, 0x01, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x12, 0x46, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 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, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x49, 0x0a, 0x04, 0x48, 0x54, + 0x54, 0x50, 0x18, 0x03, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x4f, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x3b, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, - 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x41, - 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, - 0x65, 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x54, 0x4c, - 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, - 0x67, 0x22, 0x8a, 0x01, 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, - 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, - 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, - 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x54, - 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x68, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x42, 0x0a, 0x1c, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x58, 0x46, 0x6f, 0x72, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, + 0x50, 0x0a, 0x1a, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, + 0x6f, 0x78, 0x79, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x0a, + 0x14, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x4d, 0x65, 0x73, + 0x68, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4f, 0x6e, 0x6c, + 0x79, 0x22, 0xc9, 0x01, 0x0a, 0x0d, 0x4d, 0x65, 0x73, 0x68, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x5b, 0x0a, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, + 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x54, 0x4c, 0x53, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, + 0x12, 0x5b, 0x0a, 0x08, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x3f, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x44, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x08, 0x4f, 0x75, 0x74, 0x67, 0x6f, 0x69, 0x6e, 0x67, 0x22, 0x8a, 0x01, + 0x0a, 0x18, 0x4d, 0x65, 0x73, 0x68, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, + 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, + 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, + 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x0e, 0x4d, 0x65, + 0x73, 0x68, 0x48, 0x54, 0x54, 0x50, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x1c, + 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x58, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, + 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x1c, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x58, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x65, 0x72, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1c, 0x53, 0x61, 0x6e, 0x69, 0x74, 0x69, 0x7a, 0x65, - 0x58, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x64, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x43, 0x65, 0x72, 0x74, 0x22, 0xc0, 0x05, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x43, - 0x0a, 0x07, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x53, 0x75, - 0x62, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x53, 0x75, 0x62, 0x73, - 0x65, 0x74, 0x73, 0x12, 0x40, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x22, 0xf6, 0x06, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x53, + 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x44, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x5d, 0x0a, 0x07, 0x53, 0x75, + 0x62, 0x73, 0x65, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x72, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x07, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x12, 0x5a, 0x0a, 0x08, 0x52, 0x65, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x52, 0x08, 0x52, 0x65, 0x64, - 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x46, 0x0a, 0x08, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, - 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x08, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x41, 0x0a, - 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x12, 0x3d, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x72, 0x52, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, - 0x3a, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x5e, 0x0a, 0x0c, 0x53, - 0x75, 0x62, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x38, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x61, 0x0a, 0x0d, 0x46, - 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x3a, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, - 0x76, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 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, 0x51, 0x0a, 0x15, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x6e, 0x6c, 0x79, - 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x4f, - 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x22, 0xb5, 0x01, 0x0a, 0x17, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x52, 0x65, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, - 0x65, 0x72, 0x22, 0x99, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x18, - 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x1c, - 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0xf9, - 0x01, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, - 0x16, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x43, 0x0a, 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, - 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x69, - 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x52, 0x69, - 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x12, - 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, - 0x0c, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x60, 0x0a, 0x08, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, + 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, + 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x46, + 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x57, 0x0a, 0x0c, 0x4c, 0x6f, + 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 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, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x72, 0x52, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x78, 0x0a, 0x0c, 0x53, 0x75, 0x62, + 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x52, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3c, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x1a, 0x7b, 0x0a, 0x0d, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x54, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, + 0x6c, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 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, 0x51, 0x0a, 0x15, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x53, 0x75, 0x62, 0x73, + 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x6e, + 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0b, 0x4f, 0x6e, 0x6c, 0x79, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x22, 0xb5, 0x01, 0x0a, + 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, + 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, + 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, + 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x22, 0x99, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x46, 0x61, 0x69, 0x6c, 0x6f, 0x76, 0x65, 0x72, + 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x75, 0x62, 0x73, 0x65, 0x74, + 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x73, + 0x22, 0xc7, 0x02, 0x0a, 0x0c, 0x4c, 0x6f, 0x61, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x72, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x5d, 0x0a, 0x0e, 0x52, 0x69, 0x6e, + 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 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, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, + 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, + 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x69, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x4c, 0x65, 0x61, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x55, 0x0a, 0x0c, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x0c, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x22, 0x64, 0x0a, 0x0e, 0x52, 0x69, 0x6e, 0x67, 0x48, 0x61, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x0f, @@ -2434,184 +2473,223 @@ var file_proto_pbconfigentry_config_entry_proto_rawDesc = []byte{ 0x22, 0x36, 0x0a, 0x12, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x68, 0x6f, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x43, 0x68, 0x6f, - 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xb9, 0x01, 0x0a, 0x0a, 0x48, 0x61, 0x73, + 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xd3, 0x01, 0x0a, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, + 0x09, 0x52, 0x0a, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x57, 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, - 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x50, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x50, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x54, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x69, 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, - 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x54, 0x4c, 0x12, 0x12, 0x0a, 0x04, 0x50, - 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, - 0xf1, 0x01, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x12, 0x2f, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, - 0x54, 0x4c, 0x53, 0x12, 0x3a, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, - 0x39, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, - 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 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, 0xd0, 0x01, 0x0a, 0x10, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, - 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x32, 0x0a, 0x03, 0x53, 0x44, 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x03, 0x53, 0x44, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, - 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x0a, 0x0d, - 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, - 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, - 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x13, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, - 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x22, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x22, 0xab, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x4c, - 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x37, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x12, 0x2f, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, - 0x53, 0x22, 0xbc, 0x03, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x48, 0x6f, 0x73, 0x74, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x36, - 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, + 0x01, 0x28, 0x0b, 0x32, 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, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6f, 0x6b, + 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x50, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x50, 0x12, 0x1a, 0x0a, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x22, 0x69, + 0x0a, 0x0c, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, + 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x03, 0x54, 0x54, 0x4c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x22, 0xbf, 0x02, 0x0a, 0x0e, 0x49, 0x6e, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x49, 0x0a, 0x03, + 0x54, 0x4c, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x54, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, + 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x53, 0x0a, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 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, 0xea, 0x01, 0x0a, 0x10, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x18, 0x0a, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x07, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x4c, 0x0a, 0x03, 0x53, 0x44, + 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, + 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, + 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x4d, 0x61, 0x78, 0x56, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, + 0x69, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x69, 0x70, 0x68, + 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0x5b, 0x0a, 0x13, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x20, 0x0a, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xdf, 0x01, 0x0a, 0x0f, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, + 0x73, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, + 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x51, 0x0a, 0x08, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x52, 0x08, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x49, 0x0a, 0x03, + 0x54, 0x4c, 0x53, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x22, 0xbe, 0x04, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, + 0x65, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x48, + 0x6f, 0x73, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x3e, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x48, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, - 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, - 0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, - 0x12, 0x4a, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x0f, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x04, - 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x3e, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 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, 0x4d, 0x0a, 0x17, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x0a, 0x03, 0x53, - 0x44, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, - 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, 0x53, 0x22, - 0x97, 0x02, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, - 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x3b, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, - 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x03, 0x41, 0x64, 0x64, 0x12, 0x3b, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x29, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, - 0x65, 0x72, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x53, 0x65, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, + 0x67, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x12, 0x62, 0x0a, 0x0e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, 0x0e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x12, 0x64, 0x0a, 0x0f, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, + 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x52, + 0x0f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, + 0x12, 0x53, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, + 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, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, + 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 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, 0x67, 0x0a, 0x17, 0x47, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x03, 0x53, 0x44, 0x53, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x54, 0x4c, 0x53, 0x53, 0x44, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x03, 0x53, 0x44, + 0x53, 0x22, 0xcb, 0x02, 0x0a, 0x13, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x12, 0x55, 0x0a, 0x03, 0x41, 0x64, 0x64, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, + 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x73, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x41, 0x64, 0x64, + 0x12, 0x55, 0x0a, 0x03, 0x53, 0x65, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x72, 0x73, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x03, 0x53, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x1a, + 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 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, 0x1a, 0x36, 0x0a, 0x08, 0x53, 0x65, 0x74, 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, + 0xf6, 0x01, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x50, 0x0a, 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, 0xa6, 0x06, 0x0a, 0x0f, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x4e, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, + 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x5c, 0x0a, 0x0b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x52, 0x0b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, + 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, 0x12, 0x4e, 0x0a, 0x04, 0x54, 0x79, + 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x66, 0x0a, 0x0a, + 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x46, 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, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, + 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, + 0x4d, 0x65, 0x74, 0x61, 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, + 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x46, 0x0a, 0x10, + 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x54, 0x69, 0x6d, 0x65, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, + 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, + 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, + 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x65, + 0x65, 0x72, 0x1a, 0x3d, 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 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, 0x1a, 0x36, 0x0a, 0x08, 0x53, 0x65, 0x74, 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, 0xc2, 0x01, 0x0a, 0x11, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x36, 0x0a, 0x07, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3c, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 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, 0xa4, - 0x05, 0x0a, 0x0f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x0a, 0x0b, - 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, - 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x50, 0x72, 0x65, 0x63, 0x65, 0x64, 0x65, 0x6e, 0x63, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x49, 0x44, 0x12, 0x34, 0x0a, 0x04, - 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, - 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4c, 0x0a, 0x0a, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, - 0x74, 0x61, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x4d, 0x65, - 0x74, 0x61, 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x4c, 0x65, - 0x67, 0x61, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x10, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x1a, 0x3d, 0x0a, 0x0f, 0x4c, 0x65, 0x67, 0x61, 0x63, 0x79, - 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, 0x85, 0x01, 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, - 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x41, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x01, 0x22, 0xb9, 0x01, 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x06, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x04, 0x48, 0x54, 0x54, + 0x50, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x22, 0xd3, 0x01, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x22, 0xed, 0x01, 0x0a, 0x17, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, @@ -2619,47 +2697,57 @@ var file_proto_pbconfigentry_config_entry_proto_rawDesc = []byte{ 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x61, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x74, 0x68, - 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x42, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, - 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, - 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x73, 0x22, 0xc1, 0x01, 0x0a, 0x1d, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, - 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x72, 0x65, - 0x73, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x50, 0x72, 0x65, 0x73, - 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x45, 0x78, 0x61, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, - 0x78, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x53, 0x75, 0x66, 0x66, 0x69, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x65, 0x67, - 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, - 0x16, 0x0a, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x2a, 0x77, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, - 0x0f, 0x0a, 0x0b, 0x4b, 0x69, 0x6e, 0x64, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, - 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x10, 0x02, 0x12, 0x16, 0x0a, - 0x12, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x04, - 0x2a, 0x26, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x09, 0x0a, - 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x0a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x10, 0x00, 0x42, 0xa0, 0x01, 0x0a, 0x0f, - 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, - 0x10, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x2f, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x0b, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, 0x02, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xe2, 0x02, 0x17, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0xea, 0x02, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x62, 0x06, + 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x5c, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x44, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x22, 0xc1, 0x01, + 0x0a, 0x1d, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x54, 0x54, 0x50, 0x48, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, + 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x50, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, + 0x05, 0x45, 0x78, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x45, 0x78, + 0x61, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x53, + 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x75, 0x66, + 0x66, 0x69, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x6e, 0x76, + 0x65, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x49, 0x6e, 0x76, 0x65, 0x72, + 0x74, 0x2a, 0x77, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x69, 0x6e, + 0x64, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, + 0x6e, 0x64, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x01, 0x12, 0x17, + 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x72, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x69, 0x6e, 0x64, 0x49, + 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x03, 0x12, + 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x04, 0x2a, 0x26, 0x0a, 0x0f, 0x49, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, + 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, + 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x10, 0x00, 0x42, 0xa6, 0x02, 0x0a, 0x29, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x42, 0x10, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2f, 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, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x43, 0xaa, + 0x02, 0x25, 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, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, 0x02, 0x25, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xe2, + 0x02, 0x31, 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, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } @@ -2678,104 +2766,104 @@ func file_proto_pbconfigentry_config_entry_proto_rawDescGZIP() []byte { var file_proto_pbconfigentry_config_entry_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_proto_pbconfigentry_config_entry_proto_msgTypes = make([]protoimpl.MessageInfo, 37) var file_proto_pbconfigentry_config_entry_proto_goTypes = []interface{}{ - (Kind)(0), // 0: configentry.Kind - (IntentionAction)(0), // 1: configentry.IntentionAction - (IntentionSourceType)(0), // 2: configentry.IntentionSourceType - (*ConfigEntry)(nil), // 3: configentry.ConfigEntry - (*MeshConfig)(nil), // 4: configentry.MeshConfig - (*TransparentProxyMeshConfig)(nil), // 5: configentry.TransparentProxyMeshConfig - (*MeshTLSConfig)(nil), // 6: configentry.MeshTLSConfig - (*MeshDirectionalTLSConfig)(nil), // 7: configentry.MeshDirectionalTLSConfig - (*MeshHTTPConfig)(nil), // 8: configentry.MeshHTTPConfig - (*ServiceResolver)(nil), // 9: configentry.ServiceResolver - (*ServiceResolverSubset)(nil), // 10: configentry.ServiceResolverSubset - (*ServiceResolverRedirect)(nil), // 11: configentry.ServiceResolverRedirect - (*ServiceResolverFailover)(nil), // 12: configentry.ServiceResolverFailover - (*LoadBalancer)(nil), // 13: configentry.LoadBalancer - (*RingHashConfig)(nil), // 14: configentry.RingHashConfig - (*LeastRequestConfig)(nil), // 15: configentry.LeastRequestConfig - (*HashPolicy)(nil), // 16: configentry.HashPolicy - (*CookieConfig)(nil), // 17: configentry.CookieConfig - (*IngressGateway)(nil), // 18: configentry.IngressGateway - (*GatewayTLSConfig)(nil), // 19: configentry.GatewayTLSConfig - (*GatewayTLSSDSConfig)(nil), // 20: configentry.GatewayTLSSDSConfig - (*IngressListener)(nil), // 21: configentry.IngressListener - (*IngressService)(nil), // 22: configentry.IngressService - (*GatewayServiceTLSConfig)(nil), // 23: configentry.GatewayServiceTLSConfig - (*HTTPHeaderModifiers)(nil), // 24: configentry.HTTPHeaderModifiers - (*ServiceIntentions)(nil), // 25: configentry.ServiceIntentions - (*SourceIntention)(nil), // 26: configentry.SourceIntention - (*IntentionPermission)(nil), // 27: configentry.IntentionPermission - (*IntentionHTTPPermission)(nil), // 28: configentry.IntentionHTTPPermission - (*IntentionHTTPHeaderPermission)(nil), // 29: configentry.IntentionHTTPHeaderPermission - nil, // 30: configentry.MeshConfig.MetaEntry - nil, // 31: configentry.ServiceResolver.SubsetsEntry - nil, // 32: configentry.ServiceResolver.FailoverEntry - nil, // 33: configentry.ServiceResolver.MetaEntry - nil, // 34: configentry.IngressGateway.MetaEntry - nil, // 35: configentry.IngressService.MetaEntry - nil, // 36: configentry.HTTPHeaderModifiers.AddEntry - nil, // 37: configentry.HTTPHeaderModifiers.SetEntry - nil, // 38: configentry.ServiceIntentions.MetaEntry - nil, // 39: configentry.SourceIntention.LegacyMetaEntry - (*pbcommon.EnterpriseMeta)(nil), // 40: common.EnterpriseMeta - (*pbcommon.RaftIndex)(nil), // 41: common.RaftIndex + (Kind)(0), // 0: hashicorp.consul.internal.configentry.Kind + (IntentionAction)(0), // 1: hashicorp.consul.internal.configentry.IntentionAction + (IntentionSourceType)(0), // 2: hashicorp.consul.internal.configentry.IntentionSourceType + (*ConfigEntry)(nil), // 3: hashicorp.consul.internal.configentry.ConfigEntry + (*MeshConfig)(nil), // 4: hashicorp.consul.internal.configentry.MeshConfig + (*TransparentProxyMeshConfig)(nil), // 5: hashicorp.consul.internal.configentry.TransparentProxyMeshConfig + (*MeshTLSConfig)(nil), // 6: hashicorp.consul.internal.configentry.MeshTLSConfig + (*MeshDirectionalTLSConfig)(nil), // 7: hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + (*MeshHTTPConfig)(nil), // 8: hashicorp.consul.internal.configentry.MeshHTTPConfig + (*ServiceResolver)(nil), // 9: hashicorp.consul.internal.configentry.ServiceResolver + (*ServiceResolverSubset)(nil), // 10: hashicorp.consul.internal.configentry.ServiceResolverSubset + (*ServiceResolverRedirect)(nil), // 11: hashicorp.consul.internal.configentry.ServiceResolverRedirect + (*ServiceResolverFailover)(nil), // 12: hashicorp.consul.internal.configentry.ServiceResolverFailover + (*LoadBalancer)(nil), // 13: hashicorp.consul.internal.configentry.LoadBalancer + (*RingHashConfig)(nil), // 14: hashicorp.consul.internal.configentry.RingHashConfig + (*LeastRequestConfig)(nil), // 15: hashicorp.consul.internal.configentry.LeastRequestConfig + (*HashPolicy)(nil), // 16: hashicorp.consul.internal.configentry.HashPolicy + (*CookieConfig)(nil), // 17: hashicorp.consul.internal.configentry.CookieConfig + (*IngressGateway)(nil), // 18: hashicorp.consul.internal.configentry.IngressGateway + (*GatewayTLSConfig)(nil), // 19: hashicorp.consul.internal.configentry.GatewayTLSConfig + (*GatewayTLSSDSConfig)(nil), // 20: hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + (*IngressListener)(nil), // 21: hashicorp.consul.internal.configentry.IngressListener + (*IngressService)(nil), // 22: hashicorp.consul.internal.configentry.IngressService + (*GatewayServiceTLSConfig)(nil), // 23: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig + (*HTTPHeaderModifiers)(nil), // 24: hashicorp.consul.internal.configentry.HTTPHeaderModifiers + (*ServiceIntentions)(nil), // 25: hashicorp.consul.internal.configentry.ServiceIntentions + (*SourceIntention)(nil), // 26: hashicorp.consul.internal.configentry.SourceIntention + (*IntentionPermission)(nil), // 27: hashicorp.consul.internal.configentry.IntentionPermission + (*IntentionHTTPPermission)(nil), // 28: hashicorp.consul.internal.configentry.IntentionHTTPPermission + (*IntentionHTTPHeaderPermission)(nil), // 29: hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission + nil, // 30: hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + nil, // 31: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + nil, // 32: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + nil, // 33: hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + nil, // 34: hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + nil, // 35: hashicorp.consul.internal.configentry.IngressService.MetaEntry + nil, // 36: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + nil, // 37: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + nil, // 38: hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + nil, // 39: hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + (*pbcommon.EnterpriseMeta)(nil), // 40: hashicorp.consul.internal.common.EnterpriseMeta + (*pbcommon.RaftIndex)(nil), // 41: hashicorp.consul.internal.common.RaftIndex (*durationpb.Duration)(nil), // 42: google.protobuf.Duration (*timestamppb.Timestamp)(nil), // 43: google.protobuf.Timestamp } var file_proto_pbconfigentry_config_entry_proto_depIdxs = []int32{ - 0, // 0: configentry.ConfigEntry.Kind:type_name -> configentry.Kind - 40, // 1: configentry.ConfigEntry.EnterpriseMeta:type_name -> common.EnterpriseMeta - 41, // 2: configentry.ConfigEntry.RaftIndex:type_name -> common.RaftIndex - 4, // 3: configentry.ConfigEntry.MeshConfig:type_name -> configentry.MeshConfig - 9, // 4: configentry.ConfigEntry.ServiceResolver:type_name -> configentry.ServiceResolver - 18, // 5: configentry.ConfigEntry.IngressGateway:type_name -> configentry.IngressGateway - 25, // 6: configentry.ConfigEntry.ServiceIntentions:type_name -> configentry.ServiceIntentions - 5, // 7: configentry.MeshConfig.TransparentProxy:type_name -> configentry.TransparentProxyMeshConfig - 6, // 8: configentry.MeshConfig.TLS:type_name -> configentry.MeshTLSConfig - 8, // 9: configentry.MeshConfig.HTTP:type_name -> configentry.MeshHTTPConfig - 30, // 10: configentry.MeshConfig.Meta:type_name -> configentry.MeshConfig.MetaEntry - 7, // 11: configentry.MeshTLSConfig.Incoming:type_name -> configentry.MeshDirectionalTLSConfig - 7, // 12: configentry.MeshTLSConfig.Outgoing:type_name -> configentry.MeshDirectionalTLSConfig - 31, // 13: configentry.ServiceResolver.Subsets:type_name -> configentry.ServiceResolver.SubsetsEntry - 11, // 14: configentry.ServiceResolver.Redirect:type_name -> configentry.ServiceResolverRedirect - 32, // 15: configentry.ServiceResolver.Failover:type_name -> configentry.ServiceResolver.FailoverEntry - 42, // 16: configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration - 13, // 17: configentry.ServiceResolver.LoadBalancer:type_name -> configentry.LoadBalancer - 33, // 18: configentry.ServiceResolver.Meta:type_name -> configentry.ServiceResolver.MetaEntry - 14, // 19: configentry.LoadBalancer.RingHashConfig:type_name -> configentry.RingHashConfig - 15, // 20: configentry.LoadBalancer.LeastRequestConfig:type_name -> configentry.LeastRequestConfig - 16, // 21: configentry.LoadBalancer.HashPolicies:type_name -> configentry.HashPolicy - 17, // 22: configentry.HashPolicy.CookieConfig:type_name -> configentry.CookieConfig - 42, // 23: configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration - 19, // 24: configentry.IngressGateway.TLS:type_name -> configentry.GatewayTLSConfig - 21, // 25: configentry.IngressGateway.Listeners:type_name -> configentry.IngressListener - 34, // 26: configentry.IngressGateway.Meta:type_name -> configentry.IngressGateway.MetaEntry - 20, // 27: configentry.GatewayTLSConfig.SDS:type_name -> configentry.GatewayTLSSDSConfig - 22, // 28: configentry.IngressListener.Services:type_name -> configentry.IngressService - 19, // 29: configentry.IngressListener.TLS:type_name -> configentry.GatewayTLSConfig - 23, // 30: configentry.IngressService.TLS:type_name -> configentry.GatewayServiceTLSConfig - 24, // 31: configentry.IngressService.RequestHeaders:type_name -> configentry.HTTPHeaderModifiers - 24, // 32: configentry.IngressService.ResponseHeaders:type_name -> configentry.HTTPHeaderModifiers - 35, // 33: configentry.IngressService.Meta:type_name -> configentry.IngressService.MetaEntry - 40, // 34: configentry.IngressService.EnterpriseMeta:type_name -> common.EnterpriseMeta - 20, // 35: configentry.GatewayServiceTLSConfig.SDS:type_name -> configentry.GatewayTLSSDSConfig - 36, // 36: configentry.HTTPHeaderModifiers.Add:type_name -> configentry.HTTPHeaderModifiers.AddEntry - 37, // 37: configentry.HTTPHeaderModifiers.Set:type_name -> configentry.HTTPHeaderModifiers.SetEntry - 26, // 38: configentry.ServiceIntentions.Sources:type_name -> configentry.SourceIntention - 38, // 39: configentry.ServiceIntentions.Meta:type_name -> configentry.ServiceIntentions.MetaEntry - 1, // 40: configentry.SourceIntention.Action:type_name -> configentry.IntentionAction - 27, // 41: configentry.SourceIntention.Permissions:type_name -> configentry.IntentionPermission - 2, // 42: configentry.SourceIntention.Type:type_name -> configentry.IntentionSourceType - 39, // 43: configentry.SourceIntention.LegacyMeta:type_name -> configentry.SourceIntention.LegacyMetaEntry - 43, // 44: configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp - 43, // 45: configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp - 40, // 46: configentry.SourceIntention.EnterpriseMeta:type_name -> common.EnterpriseMeta - 1, // 47: configentry.IntentionPermission.Action:type_name -> configentry.IntentionAction - 28, // 48: configentry.IntentionPermission.HTTP:type_name -> configentry.IntentionHTTPPermission - 29, // 49: configentry.IntentionHTTPPermission.Header:type_name -> configentry.IntentionHTTPHeaderPermission - 10, // 50: configentry.ServiceResolver.SubsetsEntry.value:type_name -> configentry.ServiceResolverSubset - 12, // 51: configentry.ServiceResolver.FailoverEntry.value:type_name -> configentry.ServiceResolverFailover + 0, // 0: hashicorp.consul.internal.configentry.ConfigEntry.Kind:type_name -> hashicorp.consul.internal.configentry.Kind + 40, // 1: hashicorp.consul.internal.configentry.ConfigEntry.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 41, // 2: hashicorp.consul.internal.configentry.ConfigEntry.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex + 4, // 3: hashicorp.consul.internal.configentry.ConfigEntry.MeshConfig:type_name -> hashicorp.consul.internal.configentry.MeshConfig + 9, // 4: hashicorp.consul.internal.configentry.ConfigEntry.ServiceResolver:type_name -> hashicorp.consul.internal.configentry.ServiceResolver + 18, // 5: hashicorp.consul.internal.configentry.ConfigEntry.IngressGateway:type_name -> hashicorp.consul.internal.configentry.IngressGateway + 25, // 6: hashicorp.consul.internal.configentry.ConfigEntry.ServiceIntentions:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions + 5, // 7: hashicorp.consul.internal.configentry.MeshConfig.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyMeshConfig + 6, // 8: hashicorp.consul.internal.configentry.MeshConfig.TLS:type_name -> hashicorp.consul.internal.configentry.MeshTLSConfig + 8, // 9: hashicorp.consul.internal.configentry.MeshConfig.HTTP:type_name -> hashicorp.consul.internal.configentry.MeshHTTPConfig + 30, // 10: hashicorp.consul.internal.configentry.MeshConfig.Meta:type_name -> hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + 7, // 11: hashicorp.consul.internal.configentry.MeshTLSConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + 7, // 12: hashicorp.consul.internal.configentry.MeshTLSConfig.Outgoing:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + 31, // 13: hashicorp.consul.internal.configentry.ServiceResolver.Subsets:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + 11, // 14: hashicorp.consul.internal.configentry.ServiceResolver.Redirect:type_name -> hashicorp.consul.internal.configentry.ServiceResolverRedirect + 32, // 15: hashicorp.consul.internal.configentry.ServiceResolver.Failover:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + 42, // 16: hashicorp.consul.internal.configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration + 13, // 17: hashicorp.consul.internal.configentry.ServiceResolver.LoadBalancer:type_name -> hashicorp.consul.internal.configentry.LoadBalancer + 33, // 18: hashicorp.consul.internal.configentry.ServiceResolver.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + 14, // 19: hashicorp.consul.internal.configentry.LoadBalancer.RingHashConfig:type_name -> hashicorp.consul.internal.configentry.RingHashConfig + 15, // 20: hashicorp.consul.internal.configentry.LoadBalancer.LeastRequestConfig:type_name -> hashicorp.consul.internal.configentry.LeastRequestConfig + 16, // 21: hashicorp.consul.internal.configentry.LoadBalancer.HashPolicies:type_name -> hashicorp.consul.internal.configentry.HashPolicy + 17, // 22: hashicorp.consul.internal.configentry.HashPolicy.CookieConfig:type_name -> hashicorp.consul.internal.configentry.CookieConfig + 42, // 23: hashicorp.consul.internal.configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration + 19, // 24: hashicorp.consul.internal.configentry.IngressGateway.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig + 21, // 25: hashicorp.consul.internal.configentry.IngressGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.IngressListener + 34, // 26: hashicorp.consul.internal.configentry.IngressGateway.Meta:type_name -> hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + 20, // 27: hashicorp.consul.internal.configentry.GatewayTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + 22, // 28: hashicorp.consul.internal.configentry.IngressListener.Services:type_name -> hashicorp.consul.internal.configentry.IngressService + 19, // 29: hashicorp.consul.internal.configentry.IngressListener.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig + 23, // 30: hashicorp.consul.internal.configentry.IngressService.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayServiceTLSConfig + 24, // 31: hashicorp.consul.internal.configentry.IngressService.RequestHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers + 24, // 32: hashicorp.consul.internal.configentry.IngressService.ResponseHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers + 35, // 33: hashicorp.consul.internal.configentry.IngressService.Meta:type_name -> hashicorp.consul.internal.configentry.IngressService.MetaEntry + 40, // 34: hashicorp.consul.internal.configentry.IngressService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 20, // 35: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + 36, // 36: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + 37, // 37: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + 26, // 38: hashicorp.consul.internal.configentry.ServiceIntentions.Sources:type_name -> hashicorp.consul.internal.configentry.SourceIntention + 38, // 39: hashicorp.consul.internal.configentry.ServiceIntentions.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + 1, // 40: hashicorp.consul.internal.configentry.SourceIntention.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction + 27, // 41: hashicorp.consul.internal.configentry.SourceIntention.Permissions:type_name -> hashicorp.consul.internal.configentry.IntentionPermission + 2, // 42: hashicorp.consul.internal.configentry.SourceIntention.Type:type_name -> hashicorp.consul.internal.configentry.IntentionSourceType + 39, // 43: hashicorp.consul.internal.configentry.SourceIntention.LegacyMeta:type_name -> hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + 43, // 44: hashicorp.consul.internal.configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp + 43, // 45: hashicorp.consul.internal.configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp + 40, // 46: hashicorp.consul.internal.configentry.SourceIntention.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 1, // 47: hashicorp.consul.internal.configentry.IntentionPermission.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction + 28, // 48: hashicorp.consul.internal.configentry.IntentionPermission.HTTP:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPPermission + 29, // 49: hashicorp.consul.internal.configentry.IntentionHTTPPermission.Header:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission + 10, // 50: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverSubset + 12, // 51: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailover 52, // [52:52] is the sub-list for method output_type 52, // [52:52] is the sub-list for method input_type 52, // [52:52] is the sub-list for extension type_name diff --git a/proto/pbconfigentry/config_entry.proto b/proto/pbconfigentry/config_entry.proto index 33cee09998..0a35f4ef1f 100644 --- a/proto/pbconfigentry/config_entry.proto +++ b/proto/pbconfigentry/config_entry.proto @@ -1,10 +1,10 @@ syntax = "proto3"; -import "proto/pbcommon/common.proto"; +package hashicorp.consul.internal.configentry; + import "google/protobuf/duration.proto"; import "google/protobuf/timestamp.proto"; - -package configentry; +import "proto/pbcommon/common.proto"; enum Kind { KindUnknown = 0; @@ -240,7 +240,7 @@ message IngressListener { int32 Port = 1; string Protocol = 2; repeated IngressService Services = 3; - GatewayTLSConfig TLS = 4; + GatewayTLSConfig TLS = 4; } // mog annotation: diff --git a/proto/pbconnect/connect.pb.go b/proto/pbconnect/connect.pb.go index 65f086d197..5e6adf740f 100644 --- a/proto/pbconnect/connect.pb.go +++ b/proto/pbconnect/connect.pb.go @@ -518,102 +518,120 @@ var File_proto_pbconnect_connect_proto protoreflect.FileDescriptor var file_proto_pbconnect_connect_proto_rawDesc = []byte{ 0x0a, 0x1d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x07, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa7, 0x01, 0x0a, 0x07, 0x43, 0x41, 0x52, 0x6f, 0x6f, - 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x74, - 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x52, 0x6f, 0x6f, 0x74, 0x49, 0x44, 0x12, 0x20, 0x0a, 0x0b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x54, 0x72, 0x75, - 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x25, 0x0a, 0x05, 0x52, 0x6f, 0x6f, 0x74, - 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x2e, 0x43, 0x41, 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x05, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, - 0x2f, 0x0a, 0x09, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, - 0x79, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x09, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x61, - 0x22, 0xfd, 0x04, 0x0a, 0x06, 0x43, 0x41, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, - 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x22, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, - 0x79, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x49, 0x44, 0x12, 0x30, 0x0a, 0x13, 0x45, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x54, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x54, 0x72, - 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x4e, 0x6f, 0x74, - 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x4e, 0x6f, 0x74, 0x42, 0x65, 0x66, - 0x6f, 0x72, 0x65, 0x12, 0x36, 0x0a, 0x08, 0x4e, 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x08, 0x4e, 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x52, - 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, - 0x6f, 0x6f, 0x74, 0x43, 0x65, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, - 0x43, 0x65, 0x72, 0x74, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, - 0x43, 0x65, 0x72, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x69, 0x67, 0x6e, - 0x69, 0x6e, 0x67, 0x43, 0x65, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x69, - 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x69, 0x67, - 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, - 0x3e, 0x0a, 0x0c, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x41, 0x74, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x0c, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x41, 0x74, 0x12, - 0x26, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, - 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, - 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x76, 0x61, - 0x74, 0x65, 0x4b, 0x65, 0x79, 0x42, 0x69, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x42, 0x69, 0x74, 0x73, 0x12, - 0x2f, 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x10, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, - 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, - 0x22, 0xf5, 0x03, 0x0a, 0x0a, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x12, - 0x22, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, - 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x65, 0x72, 0x74, 0x50, 0x45, 0x4d, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x43, 0x65, 0x72, 0x74, 0x50, 0x45, 0x4d, 0x12, 0x24, 0x0a, - 0x0d, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x45, 0x4d, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, - 0x50, 0x45, 0x4d, 0x12, 0x18, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1e, 0x0a, - 0x0a, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x52, 0x49, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x55, 0x52, 0x49, 0x12, 0x14, 0x0a, - 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x67, - 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x55, 0x52, 0x49, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x55, 0x52, 0x49, 0x12, - 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, - 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x4b, 0x69, 0x6e, 0x64, 0x55, 0x52, 0x49, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4b, 0x69, 0x6e, 0x64, 0x55, 0x52, 0x49, 0x12, 0x3a, 0x0a, - 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x3c, 0x0a, 0x0b, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x56, 0x61, 0x6c, 0x69, - 0x64, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x3e, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x16, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, - 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, + 0x21, 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, 0x6e, 0x65, + 0x63, 0x74, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0xdb, 0x01, 0x0a, 0x07, 0x43, 0x41, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x0c, + 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0c, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x49, 0x44, + 0x12, 0x20, 0x0a, 0x0b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, + 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x05, 0x52, 0x6f, 0x6f, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x29, 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, 0x6e, 0x65, 0x63, 0x74, 0x2e, 0x43, 0x41, 0x52, 0x6f, 0x6f, 0x74, 0x52, 0x05, 0x52, 0x6f, + 0x6f, 0x74, 0x73, 0x12, 0x49, 0x0a, 0x09, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x61, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, + 0x65, 0x74, 0x61, 0x52, 0x09, 0x51, 0x75, 0x65, 0x72, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x22, 0x97, + 0x05, 0x0a, 0x06, 0x43, 0x41, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, + 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, + 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x49, + 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, + 0x4b, 0x65, 0x79, 0x49, 0x44, 0x12, 0x30, 0x0a, 0x13, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x54, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x13, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x4e, 0x6f, 0x74, 0x42, 0x65, + 0x66, 0x6f, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x4e, 0x6f, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, + 0x65, 0x12, 0x36, 0x0a, 0x08, 0x4e, 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x08, 0x4e, 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x6f, 0x6f, + 0x74, 0x43, 0x65, 0x72, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x52, 0x6f, 0x6f, + 0x74, 0x43, 0x65, 0x72, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, + 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x11, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x43, 0x65, + 0x72, 0x74, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x43, 0x65, + 0x72, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, + 0x67, 0x43, 0x65, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, + 0x4b, 0x65, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x69, 0x67, 0x6e, 0x69, + 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x12, 0x3e, 0x0a, + 0x0c, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x41, 0x74, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x0c, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x64, 0x4f, 0x75, 0x74, 0x41, 0x74, 0x12, 0x26, 0x0a, + 0x0e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, + 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x42, 0x69, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x50, + 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x42, 0x69, 0x74, 0x73, 0x12, 0x49, 0x0a, + 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2b, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, - 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x42, 0x84, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, - 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x42, 0x0c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0xa2, 0x02, 0x03, 0x43, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0xca, 0x02, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0xe2, - 0x02, 0x13, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0xa9, 0x04, 0x0a, 0x0a, 0x49, 0x73, 0x73, + 0x75, 0x65, 0x64, 0x43, 0x65, 0x72, 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x69, 0x61, + 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x53, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x43, + 0x65, 0x72, 0x74, 0x50, 0x45, 0x4d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x43, 0x65, + 0x72, 0x74, 0x50, 0x45, 0x4d, 0x12, 0x24, 0x0a, 0x0d, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x50, 0x45, 0x4d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x50, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x45, 0x4d, 0x12, 0x18, 0x0a, 0x07, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x55, 0x52, 0x49, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x55, 0x52, 0x49, 0x12, 0x14, 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x41, + 0x67, 0x65, 0x6e, 0x74, 0x55, 0x52, 0x49, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x41, + 0x67, 0x65, 0x6e, 0x74, 0x55, 0x52, 0x49, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, + 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x4b, + 0x69, 0x6e, 0x64, 0x55, 0x52, 0x49, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x4b, 0x69, + 0x6e, 0x64, 0x55, 0x52, 0x49, 0x12, 0x3a, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x66, + 0x74, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x41, 0x66, 0x74, 0x65, + 0x72, 0x12, 0x3c, 0x0a, 0x0b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x52, 0x0b, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, + 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, + 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x49, 0x0a, 0x09, 0x52, 0x61, 0x66, + 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x42, 0x8a, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x42, 0x0c, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0xa2, 0x02, 0x04, 0x48, 0x43, + 0x49, 0x43, 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, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 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, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 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, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 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, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -630,25 +648,25 @@ func file_proto_pbconnect_connect_proto_rawDescGZIP() []byte { var file_proto_pbconnect_connect_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_proto_pbconnect_connect_proto_goTypes = []interface{}{ - (*CARoots)(nil), // 0: connect.CARoots - (*CARoot)(nil), // 1: connect.CARoot - (*IssuedCert)(nil), // 2: connect.IssuedCert - (*pbcommon.QueryMeta)(nil), // 3: common.QueryMeta + (*CARoots)(nil), // 0: hashicorp.consul.internal.connect.CARoots + (*CARoot)(nil), // 1: hashicorp.consul.internal.connect.CARoot + (*IssuedCert)(nil), // 2: hashicorp.consul.internal.connect.IssuedCert + (*pbcommon.QueryMeta)(nil), // 3: hashicorp.consul.internal.common.QueryMeta (*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp - (*pbcommon.RaftIndex)(nil), // 5: common.RaftIndex - (*pbcommon.EnterpriseMeta)(nil), // 6: common.EnterpriseMeta + (*pbcommon.RaftIndex)(nil), // 5: hashicorp.consul.internal.common.RaftIndex + (*pbcommon.EnterpriseMeta)(nil), // 6: hashicorp.consul.internal.common.EnterpriseMeta } var file_proto_pbconnect_connect_proto_depIdxs = []int32{ - 1, // 0: connect.CARoots.Roots:type_name -> connect.CARoot - 3, // 1: connect.CARoots.QueryMeta:type_name -> common.QueryMeta - 4, // 2: connect.CARoot.NotBefore:type_name -> google.protobuf.Timestamp - 4, // 3: connect.CARoot.NotAfter:type_name -> google.protobuf.Timestamp - 4, // 4: connect.CARoot.RotatedOutAt:type_name -> google.protobuf.Timestamp - 5, // 5: connect.CARoot.RaftIndex:type_name -> common.RaftIndex - 4, // 6: connect.IssuedCert.ValidAfter:type_name -> google.protobuf.Timestamp - 4, // 7: connect.IssuedCert.ValidBefore:type_name -> google.protobuf.Timestamp - 6, // 8: connect.IssuedCert.EnterpriseMeta:type_name -> common.EnterpriseMeta - 5, // 9: connect.IssuedCert.RaftIndex:type_name -> common.RaftIndex + 1, // 0: hashicorp.consul.internal.connect.CARoots.Roots:type_name -> hashicorp.consul.internal.connect.CARoot + 3, // 1: hashicorp.consul.internal.connect.CARoots.QueryMeta:type_name -> hashicorp.consul.internal.common.QueryMeta + 4, // 2: hashicorp.consul.internal.connect.CARoot.NotBefore:type_name -> google.protobuf.Timestamp + 4, // 3: hashicorp.consul.internal.connect.CARoot.NotAfter:type_name -> google.protobuf.Timestamp + 4, // 4: hashicorp.consul.internal.connect.CARoot.RotatedOutAt:type_name -> google.protobuf.Timestamp + 5, // 5: hashicorp.consul.internal.connect.CARoot.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex + 4, // 6: hashicorp.consul.internal.connect.IssuedCert.ValidAfter:type_name -> google.protobuf.Timestamp + 4, // 7: hashicorp.consul.internal.connect.IssuedCert.ValidBefore:type_name -> google.protobuf.Timestamp + 6, // 8: hashicorp.consul.internal.connect.IssuedCert.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 5, // 9: hashicorp.consul.internal.connect.IssuedCert.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex 10, // [10:10] is the sub-list for method output_type 10, // [10:10] is the sub-list for method input_type 10, // [10:10] is the sub-list for extension type_name diff --git a/proto/pbconnect/connect.proto b/proto/pbconnect/connect.proto index 4dbb8bb5ff..6409873165 100644 --- a/proto/pbconnect/connect.proto +++ b/proto/pbconnect/connect.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package connect; +package hashicorp.consul.internal.connect; import "google/protobuf/timestamp.proto"; import "proto/pbcommon/common.proto"; diff --git a/proto/pbpeering/generate.go b/proto/pbpeering/generate.go deleted file mode 100644 index 1f060a6cfe..0000000000 --- a/proto/pbpeering/generate.go +++ /dev/null @@ -1,9 +0,0 @@ -// TODO: files generated from this go:generate may fail the CI check because of relative source. -// Figure out a way to robustly use this file. -//go:generate protoc --gofast_out=. --gofast_opt=paths=source_relative --go-binary_out=. peering.proto -// requires: -// - protoc -// - github.com/gogo/protobuf/protoc-gen-gofast -// - github.com/hashicorp/protoc-gen-go-binary - -package pbpeering diff --git a/proto/pbpeering/peering.go b/proto/pbpeering/peering.go index cb26b2a56b..5de1dc9bc0 100644 --- a/proto/pbpeering/peering.go +++ b/proto/pbpeering/peering.go @@ -91,10 +91,6 @@ func (p *Peering) ShouldDial() bool { return len(p.PeerServerAddresses) > 0 } -func (x ReplicationMessage_Response_Operation) GoString() string { - return x.String() -} - func (x PeeringState) GoString() string { return x.String() } diff --git a/proto/pbpeering/peering.pb.binary.go b/proto/pbpeering/peering.pb.binary.go index c7e24ecf38..7b79410857 100644 --- a/proto/pbpeering/peering.pb.binary.go +++ b/proto/pbpeering/peering.pb.binary.go @@ -246,53 +246,3 @@ func (msg *EstablishResponse) MarshalBinary() ([]byte, error) { func (msg *EstablishResponse) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ReplicationMessage) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ReplicationMessage) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ReplicationMessage_Request) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ReplicationMessage_Request) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ReplicationMessage_Response) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ReplicationMessage_Response) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *ReplicationMessage_Terminated) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *ReplicationMessage_Terminated) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} - -// MarshalBinary implements encoding.BinaryMarshaler -func (msg *LeaderAddress) MarshalBinary() ([]byte, error) { - return proto.Marshal(msg) -} - -// UnmarshalBinary implements encoding.BinaryUnmarshaler -func (msg *LeaderAddress) UnmarshalBinary(b []byte) error { - return proto.Unmarshal(b, msg) -} diff --git a/proto/pbpeering/peering.pb.go b/proto/pbpeering/peering.pb.go index 98d1c4382c..336808b726 100644 --- a/proto/pbpeering/peering.pb.go +++ b/proto/pbpeering/peering.pb.go @@ -7,10 +7,8 @@ package pbpeering import ( - pbstatus "github.com/hashicorp/consul/proto/pbstatus" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" - anypb "google.golang.org/protobuf/types/known/anypb" timestamppb "google.golang.org/protobuf/types/known/timestamppb" reflect "reflect" sync "sync" @@ -98,60 +96,6 @@ func (PeeringState) EnumDescriptor() ([]byte, []int) { return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{0} } -// Operation enumerates supported operations for replicated resources. -type ReplicationMessage_Response_Operation int32 - -const ( - ReplicationMessage_Response_Unknown ReplicationMessage_Response_Operation = 0 - // UPSERT represents a create or update event. - ReplicationMessage_Response_UPSERT ReplicationMessage_Response_Operation = 1 - // DELETE indicates the resource should be deleted. - // In DELETE operations no Resource will be returned. - // Deletion by an importing peer must be done with the type URL and ID. - ReplicationMessage_Response_DELETE ReplicationMessage_Response_Operation = 2 -) - -// Enum value maps for ReplicationMessage_Response_Operation. -var ( - ReplicationMessage_Response_Operation_name = map[int32]string{ - 0: "Unknown", - 1: "UPSERT", - 2: "DELETE", - } - ReplicationMessage_Response_Operation_value = map[string]int32{ - "Unknown": 0, - "UPSERT": 1, - "DELETE": 2, - } -) - -func (x ReplicationMessage_Response_Operation) Enum() *ReplicationMessage_Response_Operation { - p := new(ReplicationMessage_Response_Operation) - *p = x - return p -} - -func (x ReplicationMessage_Response_Operation) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ReplicationMessage_Response_Operation) Descriptor() protoreflect.EnumDescriptor { - return file_proto_pbpeering_peering_proto_enumTypes[1].Descriptor() -} - -func (ReplicationMessage_Response_Operation) Type() protoreflect.EnumType { - return &file_proto_pbpeering_peering_proto_enumTypes[1] -} - -func (x ReplicationMessage_Response_Operation) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ReplicationMessage_Response_Operation.Descriptor instead. -func (ReplicationMessage_Response_Operation) EnumDescriptor() ([]byte, []int) { - return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{24, 1, 0} -} - // Peering defines a peering relationship between two disparate Consul clusters // // mog annotation: @@ -181,7 +125,7 @@ type Peering struct { // peering relationship. // // mog: func-to=PeeringStateToAPI func-from=PeeringStateFromAPI - State PeeringState `protobuf:"varint,6,opt,name=State,proto3,enum=peering.PeeringState" json:"State,omitempty"` + State PeeringState `protobuf:"varint,6,opt,name=State,proto3,enum=hashicorp.consul.internal.peering.PeeringState" json:"State,omitempty"` // PeerID is the ID that our peer assigned to this peering. // This ID is to be used when dialing the peer, so that it can know who dialed it. PeerID string `protobuf:"bytes,7,opt,name=PeerID,proto3" json:"PeerID,omitempty"` @@ -1685,668 +1629,320 @@ func (*EstablishResponse) Descriptor() ([]byte, []int) { return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{23} } -type ReplicationMessage struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Payload: - // *ReplicationMessage_Request_ - // *ReplicationMessage_Response_ - // *ReplicationMessage_Terminated_ - Payload isReplicationMessage_Payload `protobuf_oneof:"Payload"` -} - -func (x *ReplicationMessage) Reset() { - *x = ReplicationMessage{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_pbpeering_peering_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReplicationMessage) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReplicationMessage) ProtoMessage() {} - -func (x *ReplicationMessage) ProtoReflect() protoreflect.Message { - mi := &file_proto_pbpeering_peering_proto_msgTypes[24] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReplicationMessage.ProtoReflect.Descriptor instead. -func (*ReplicationMessage) Descriptor() ([]byte, []int) { - return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{24} -} - -func (m *ReplicationMessage) GetPayload() isReplicationMessage_Payload { - if m != nil { - return m.Payload - } - return nil -} - -func (x *ReplicationMessage) GetRequest() *ReplicationMessage_Request { - if x, ok := x.GetPayload().(*ReplicationMessage_Request_); ok { - return x.Request - } - return nil -} - -func (x *ReplicationMessage) GetResponse() *ReplicationMessage_Response { - if x, ok := x.GetPayload().(*ReplicationMessage_Response_); ok { - return x.Response - } - return nil -} - -func (x *ReplicationMessage) GetTerminated() *ReplicationMessage_Terminated { - if x, ok := x.GetPayload().(*ReplicationMessage_Terminated_); ok { - return x.Terminated - } - return nil -} - -type isReplicationMessage_Payload interface { - isReplicationMessage_Payload() -} - -type ReplicationMessage_Request_ struct { - Request *ReplicationMessage_Request `protobuf:"bytes,1,opt,name=request,proto3,oneof"` -} - -type ReplicationMessage_Response_ struct { - Response *ReplicationMessage_Response `protobuf:"bytes,2,opt,name=response,proto3,oneof"` -} - -type ReplicationMessage_Terminated_ struct { - Terminated *ReplicationMessage_Terminated `protobuf:"bytes,3,opt,name=terminated,proto3,oneof"` -} - -func (*ReplicationMessage_Request_) isReplicationMessage_Payload() {} - -func (*ReplicationMessage_Response_) isReplicationMessage_Payload() {} - -func (*ReplicationMessage_Terminated_) isReplicationMessage_Payload() {} - -// LeaderAddress is sent when the peering service runs on a consul node -// that is not a leader. The node either lost leadership, or never was a leader. -type LeaderAddress struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // address is an ip:port best effort hint at what could be the cluster leader's address - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` -} - -func (x *LeaderAddress) Reset() { - *x = LeaderAddress{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_pbpeering_peering_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *LeaderAddress) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LeaderAddress) ProtoMessage() {} - -func (x *LeaderAddress) ProtoReflect() protoreflect.Message { - mi := &file_proto_pbpeering_peering_proto_msgTypes[25] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LeaderAddress.ProtoReflect.Descriptor instead. -func (*LeaderAddress) Descriptor() ([]byte, []int) { - return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{25} -} - -func (x *LeaderAddress) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -// A Request requests to subscribe to a resource of a given type. -type ReplicationMessage_Request struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // An identifier for the peer making the request. - // This identifier is provisioned by the serving peer prior to the request from the dialing peer. - PeerID string `protobuf:"bytes,1,opt,name=PeerID,proto3" json:"PeerID,omitempty"` - // Nonce corresponding to that of the response being ACKed or NACKed. - // Initial subscription requests will have an empty nonce. - // The nonce is generated and incremented by the exporting peer. - Nonce string `protobuf:"bytes,2,opt,name=Nonce,proto3" json:"Nonce,omitempty"` - // The type URL for the resource being requested or ACK/NACKed. - ResourceURL string `protobuf:"bytes,3,opt,name=ResourceURL,proto3" json:"ResourceURL,omitempty"` - // The error if the previous response was not applied successfully. - // This field is empty in the first subscription request. - Error *pbstatus.Status `protobuf:"bytes,4,opt,name=Error,proto3" json:"Error,omitempty"` -} - -func (x *ReplicationMessage_Request) Reset() { - *x = ReplicationMessage_Request{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_pbpeering_peering_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReplicationMessage_Request) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReplicationMessage_Request) ProtoMessage() {} - -func (x *ReplicationMessage_Request) ProtoReflect() protoreflect.Message { - mi := &file_proto_pbpeering_peering_proto_msgTypes[30] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReplicationMessage_Request.ProtoReflect.Descriptor instead. -func (*ReplicationMessage_Request) Descriptor() ([]byte, []int) { - return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{24, 0} -} - -func (x *ReplicationMessage_Request) GetPeerID() string { - if x != nil { - return x.PeerID - } - return "" -} - -func (x *ReplicationMessage_Request) GetNonce() string { - if x != nil { - return x.Nonce - } - return "" -} - -func (x *ReplicationMessage_Request) GetResourceURL() string { - if x != nil { - return x.ResourceURL - } - return "" -} - -func (x *ReplicationMessage_Request) GetError() *pbstatus.Status { - if x != nil { - return x.Error - } - return nil -} - -// A Response contains resources corresponding to a subscription request. -type ReplicationMessage_Response struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Nonce identifying a response in a stream. - Nonce string `protobuf:"bytes,1,opt,name=Nonce,proto3" json:"Nonce,omitempty"` - // The type URL of resource being returned. - ResourceURL string `protobuf:"bytes,2,opt,name=ResourceURL,proto3" json:"ResourceURL,omitempty"` - // An identifier for the resource being returned. - // This could be the SPIFFE ID of the service. - ResourceID string `protobuf:"bytes,3,opt,name=ResourceID,proto3" json:"ResourceID,omitempty"` - // The resource being returned. - Resource *anypb.Any `protobuf:"bytes,4,opt,name=Resource,proto3" json:"Resource,omitempty"` - // REQUIRED. The operation to be performed in relation to the resource. - Operation ReplicationMessage_Response_Operation `protobuf:"varint,5,opt,name=operation,proto3,enum=peering.ReplicationMessage_Response_Operation" json:"operation,omitempty"` -} - -func (x *ReplicationMessage_Response) Reset() { - *x = ReplicationMessage_Response{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_pbpeering_peering_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReplicationMessage_Response) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReplicationMessage_Response) ProtoMessage() {} - -func (x *ReplicationMessage_Response) ProtoReflect() protoreflect.Message { - mi := &file_proto_pbpeering_peering_proto_msgTypes[31] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReplicationMessage_Response.ProtoReflect.Descriptor instead. -func (*ReplicationMessage_Response) Descriptor() ([]byte, []int) { - return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{24, 1} -} - -func (x *ReplicationMessage_Response) GetNonce() string { - if x != nil { - return x.Nonce - } - return "" -} - -func (x *ReplicationMessage_Response) GetResourceURL() string { - if x != nil { - return x.ResourceURL - } - return "" -} - -func (x *ReplicationMessage_Response) GetResourceID() string { - if x != nil { - return x.ResourceID - } - return "" -} - -func (x *ReplicationMessage_Response) GetResource() *anypb.Any { - if x != nil { - return x.Resource - } - return nil -} - -func (x *ReplicationMessage_Response) GetOperation() ReplicationMessage_Response_Operation { - if x != nil { - return x.Operation - } - return ReplicationMessage_Response_Unknown -} - -// Terminated is sent when a peering is deleted locally. -// This message signals to the peer that they should clean up their local state about the peering. -type ReplicationMessage_Terminated struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *ReplicationMessage_Terminated) Reset() { - *x = ReplicationMessage_Terminated{} - if protoimpl.UnsafeEnabled { - mi := &file_proto_pbpeering_peering_proto_msgTypes[32] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReplicationMessage_Terminated) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReplicationMessage_Terminated) ProtoMessage() {} - -func (x *ReplicationMessage_Terminated) ProtoReflect() protoreflect.Message { - mi := &file_proto_pbpeering_peering_proto_msgTypes[32] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReplicationMessage_Terminated.ProtoReflect.Descriptor instead. -func (*ReplicationMessage_Terminated) Descriptor() ([]byte, []int) { - return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{24, 2} -} - var File_proto_pbpeering_peering_proto protoreflect.FileDescriptor var file_proto_pbpeering_peering_proto_rawDesc = []byte{ 0x0a, 0x1d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2f, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x07, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x22, 0xd9, 0x04, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x0e, 0x0a, - 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, - 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x38, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x4d, 0x65, 0x74, - 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2b, 0x0a, 0x05, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, - 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, - 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1e, - 0x0a, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x43, 0x41, 0x50, 0x65, 0x6d, 0x73, 0x18, 0x08, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x43, 0x41, 0x50, 0x65, 0x6d, 0x73, 0x12, 0x26, - 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x0a, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x13, 0x50, 0x65, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x49, 0x6d, 0x70, 0x6f, - 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x14, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x45, 0x78, 0x70, 0x6f, - 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x21, 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, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0x8d, 0x05, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, + 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, + 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x38, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x48, 0x0a, 0x04, 0x4d, + 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x50, 0x65, + 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x45, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 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, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x65, + 0x65, 0x72, 0x49, 0x44, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x43, 0x41, 0x50, 0x65, + 0x6d, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x43, 0x41, + 0x50, 0x65, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x50, 0x65, + 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x13, + 0x50, 0x65, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x50, 0x65, 0x65, 0x72, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x32, + 0x0a, 0x14, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x14, 0x49, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x32, 0x0a, 0x14, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x14, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x6f, 0x64, 0x69, + 0x66, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4d, + 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 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, 0xfe, 0x01, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, + 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1a, 0x0a, 0x08, + 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 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, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x6f, 0x6f, 0x74, 0x50, 0x45, + 0x4d, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x52, 0x6f, 0x6f, 0x74, 0x50, 0x45, + 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x45, + 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, + 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x64, 0x65, - 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, - 0x6e, 0x64, 0x65, 0x78, 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, 0xfe, 0x01, - 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x54, 0x72, 0x75, 0x73, 0x74, 0x44, 0x6f, 0x6d, - 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x54, 0x72, 0x75, 0x73, 0x74, - 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 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, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x1a, 0x0a, 0x08, 0x52, 0x6f, 0x6f, 0x74, 0x50, 0x45, 0x4d, 0x73, 0x18, 0x04, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x08, 0x52, 0x6f, 0x6f, 0x74, 0x50, 0x45, 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x11, - 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x65, - 0x64, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0b, - 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, 0x66, - 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 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, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, - 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x41, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2a, 0x0a, - 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, + 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x22, 0x66, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 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, 0x12, 0x1e, 0x0a, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x5b, 0x0a, 0x13, + 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x52, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x43, 0x0a, + 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x5d, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x73, 0x22, 0xd6, 0x01, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x07, 0x50, 0x65, - 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x65, - 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x07, 0x50, - 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, - 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, - 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, - 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x16, 0x0a, 0x14, 0x50, - 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x68, 0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, - 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x17, 0x0a, - 0x15, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb3, 0x01, 0x0a, 0x1f, 0x54, 0x72, 0x75, 0x73, 0x74, - 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, - 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, - 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1e, 0x0a, 0x0a, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x6f, 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, 0x35, 0x0a, 0x07, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 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, 0x6a, 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, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, - 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, - 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x64, 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, 0x33, 0x0a, 0x06, 0x42, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 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, 0x8d, - 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, 0x4b, 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, 0x1b, 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, 0x12, 0x1e, - 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 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, 0x73, 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, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, - 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, - 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 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, 0xfc, 0x01, 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, 0x1e, 0x0a, - 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, - 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x12, 0x3b, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x27, 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, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, + 0x6e, 0x67, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x8a, 0x02, 0x0a, + 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, + 0x67, 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, + 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 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, 0x98, 0x02, 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, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, - 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, - 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, - 0x37, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 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, 0x22, 0x94, 0x05, 0x0a, 0x12, 0x52, 0x65, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3f, 0x0a, - 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, - 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, - 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x24, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x48, 0x0a, 0x0a, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, - 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, - 0x52, 0x0a, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x1a, 0x7f, 0x0a, 0x07, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, - 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x12, - 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x55, 0x52, 0x4c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x12, 0x24, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0x94, 0x02, - 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, - 0x6e, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x6e, 0x63, 0x65, - 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, - 0x52, 0x4c, 0x12, 0x1e, 0x0a, 0x0a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x49, 0x44, 0x12, 0x30, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x08, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2e, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x70, - 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x30, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, - 0x55, 0x50, 0x53, 0x45, 0x52, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, - 0x54, 0x45, 0x10, 0x02, 0x1a, 0x0c, 0x0a, 0x0a, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, - 0x65, 0x64, 0x42, 0x09, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x29, 0x0a, - 0x0d, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, - 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 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, 0xed, 0x05, - 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x4e, 0x0a, 0x0d, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x12, 0x1d, 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, 0x1e, 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, 0x42, 0x0a, 0x09, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x12, 0x19, 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, 0x1a, 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, 0x48, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x61, 0x64, 0x12, 0x1b, 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, 0x1c, 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, 0x48, - 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1b, 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, 0x1c, 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, 0x4e, 0x0a, 0x0d, 0x50, 0x65, 0x65, 0x72, - 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x1d, 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, 0x1e, 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, 0x4b, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, - 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x1c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, - 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 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, 0x6f, 0x0a, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x16, 0x0a, 0x14, 0x50, 0x65, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x68, 0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, + 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, + 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x17, 0x0a, 0x15, 0x50, + 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb3, 0x01, 0x0a, 0x1f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x28, 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, 0x29, 0x2e, 0x70, 0x65, - 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x12, 0x1f, 0x2e, 0x70, 0x65, 0x65, 0x72, - 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, - 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x70, 0x65, 0x65, - 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4f, 0x0a, 0x0f, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, - 0x1b, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1b, 0x2e, 0x70, - 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x84, 0x01, - 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x0c, 0x50, - 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x70, 0x62, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, - 0xaa, 0x02, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x07, 0x50, 0x65, 0x65, - 0x72, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x50, 0x65, 0x65, - 0x72, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x4e, + 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, + 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 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, 0x6a, 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, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, + 0x65, 0x72, 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, 0xa7, 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, 0x12, 0x1e, 0x0a, 0x0a, 0x44, + 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 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, 0x73, + 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, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, + 0x74, 0x65, 0x72, 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, 0x96, 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, 0x1e, 0x0a, 0x0a, 0x44, 0x61, + 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 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, 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, 0xb2, 0x02, + 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, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, + 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x51, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, + 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, 0x70, 0x65, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d, 0x50, 0x65, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x37, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, + 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7f, 0x0a, + 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x36, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, + 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, + 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa3, + 0x01, 0x0a, 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, + 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x42, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, + 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, + 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, + 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x12, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0x8a, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, + 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x70, + 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x50, 0xaa, 0x02, 0x21, + 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, + 0x67, 0xca, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x65, + 0x65, 0x72, 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x5c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2361,90 +1957,74 @@ func file_proto_pbpeering_peering_proto_rawDescGZIP() []byte { return file_proto_pbpeering_peering_proto_rawDescData } -var file_proto_pbpeering_peering_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_proto_pbpeering_peering_proto_msgTypes = make([]protoimpl.MessageInfo, 33) +var file_proto_pbpeering_peering_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_proto_pbpeering_peering_proto_msgTypes = make([]protoimpl.MessageInfo, 28) var file_proto_pbpeering_peering_proto_goTypes = []interface{}{ - (PeeringState)(0), // 0: peering.PeeringState - (ReplicationMessage_Response_Operation)(0), // 1: peering.ReplicationMessage.Response.Operation - (*Peering)(nil), // 2: peering.Peering - (*PeeringTrustBundle)(nil), // 3: peering.PeeringTrustBundle - (*PeeringReadRequest)(nil), // 4: peering.PeeringReadRequest - (*PeeringReadResponse)(nil), // 5: peering.PeeringReadResponse - (*PeeringListRequest)(nil), // 6: peering.PeeringListRequest - (*PeeringListResponse)(nil), // 7: peering.PeeringListResponse - (*PeeringWriteRequest)(nil), // 8: peering.PeeringWriteRequest - (*PeeringWriteResponse)(nil), // 9: peering.PeeringWriteResponse - (*PeeringDeleteRequest)(nil), // 10: peering.PeeringDeleteRequest - (*PeeringDeleteResponse)(nil), // 11: peering.PeeringDeleteResponse - (*TrustBundleListByServiceRequest)(nil), // 12: peering.TrustBundleListByServiceRequest - (*TrustBundleListByServiceResponse)(nil), // 13: peering.TrustBundleListByServiceResponse - (*TrustBundleReadRequest)(nil), // 14: peering.TrustBundleReadRequest - (*TrustBundleReadResponse)(nil), // 15: peering.TrustBundleReadResponse - (*PeeringTerminateByIDRequest)(nil), // 16: peering.PeeringTerminateByIDRequest - (*PeeringTerminateByIDResponse)(nil), // 17: peering.PeeringTerminateByIDResponse - (*PeeringTrustBundleWriteRequest)(nil), // 18: peering.PeeringTrustBundleWriteRequest - (*PeeringTrustBundleWriteResponse)(nil), // 19: peering.PeeringTrustBundleWriteResponse - (*PeeringTrustBundleDeleteRequest)(nil), // 20: peering.PeeringTrustBundleDeleteRequest - (*PeeringTrustBundleDeleteResponse)(nil), // 21: peering.PeeringTrustBundleDeleteResponse - (*GenerateTokenRequest)(nil), // 22: peering.GenerateTokenRequest - (*GenerateTokenResponse)(nil), // 23: peering.GenerateTokenResponse - (*EstablishRequest)(nil), // 24: peering.EstablishRequest - (*EstablishResponse)(nil), // 25: peering.EstablishResponse - (*ReplicationMessage)(nil), // 26: peering.ReplicationMessage - (*LeaderAddress)(nil), // 27: peering.LeaderAddress - nil, // 28: peering.Peering.MetaEntry - nil, // 29: peering.PeeringWriteRequest.MetaEntry - nil, // 30: peering.GenerateTokenRequest.MetaEntry - nil, // 31: peering.EstablishRequest.MetaEntry - (*ReplicationMessage_Request)(nil), // 32: peering.ReplicationMessage.Request - (*ReplicationMessage_Response)(nil), // 33: peering.ReplicationMessage.Response - (*ReplicationMessage_Terminated)(nil), // 34: peering.ReplicationMessage.Terminated - (*timestamppb.Timestamp)(nil), // 35: google.protobuf.Timestamp - (*pbstatus.Status)(nil), // 36: status.Status - (*anypb.Any)(nil), // 37: google.protobuf.Any + (PeeringState)(0), // 0: hashicorp.consul.internal.peering.PeeringState + (*Peering)(nil), // 1: hashicorp.consul.internal.peering.Peering + (*PeeringTrustBundle)(nil), // 2: hashicorp.consul.internal.peering.PeeringTrustBundle + (*PeeringReadRequest)(nil), // 3: hashicorp.consul.internal.peering.PeeringReadRequest + (*PeeringReadResponse)(nil), // 4: hashicorp.consul.internal.peering.PeeringReadResponse + (*PeeringListRequest)(nil), // 5: hashicorp.consul.internal.peering.PeeringListRequest + (*PeeringListResponse)(nil), // 6: hashicorp.consul.internal.peering.PeeringListResponse + (*PeeringWriteRequest)(nil), // 7: hashicorp.consul.internal.peering.PeeringWriteRequest + (*PeeringWriteResponse)(nil), // 8: hashicorp.consul.internal.peering.PeeringWriteResponse + (*PeeringDeleteRequest)(nil), // 9: hashicorp.consul.internal.peering.PeeringDeleteRequest + (*PeeringDeleteResponse)(nil), // 10: hashicorp.consul.internal.peering.PeeringDeleteResponse + (*TrustBundleListByServiceRequest)(nil), // 11: hashicorp.consul.internal.peering.TrustBundleListByServiceRequest + (*TrustBundleListByServiceResponse)(nil), // 12: hashicorp.consul.internal.peering.TrustBundleListByServiceResponse + (*TrustBundleReadRequest)(nil), // 13: hashicorp.consul.internal.peering.TrustBundleReadRequest + (*TrustBundleReadResponse)(nil), // 14: hashicorp.consul.internal.peering.TrustBundleReadResponse + (*PeeringTerminateByIDRequest)(nil), // 15: hashicorp.consul.internal.peering.PeeringTerminateByIDRequest + (*PeeringTerminateByIDResponse)(nil), // 16: hashicorp.consul.internal.peering.PeeringTerminateByIDResponse + (*PeeringTrustBundleWriteRequest)(nil), // 17: hashicorp.consul.internal.peering.PeeringTrustBundleWriteRequest + (*PeeringTrustBundleWriteResponse)(nil), // 18: hashicorp.consul.internal.peering.PeeringTrustBundleWriteResponse + (*PeeringTrustBundleDeleteRequest)(nil), // 19: hashicorp.consul.internal.peering.PeeringTrustBundleDeleteRequest + (*PeeringTrustBundleDeleteResponse)(nil), // 20: hashicorp.consul.internal.peering.PeeringTrustBundleDeleteResponse + (*GenerateTokenRequest)(nil), // 21: hashicorp.consul.internal.peering.GenerateTokenRequest + (*GenerateTokenResponse)(nil), // 22: hashicorp.consul.internal.peering.GenerateTokenResponse + (*EstablishRequest)(nil), // 23: hashicorp.consul.internal.peering.EstablishRequest + (*EstablishResponse)(nil), // 24: hashicorp.consul.internal.peering.EstablishResponse + nil, // 25: hashicorp.consul.internal.peering.Peering.MetaEntry + nil, // 26: hashicorp.consul.internal.peering.PeeringWriteRequest.MetaEntry + nil, // 27: hashicorp.consul.internal.peering.GenerateTokenRequest.MetaEntry + nil, // 28: hashicorp.consul.internal.peering.EstablishRequest.MetaEntry + (*timestamppb.Timestamp)(nil), // 29: google.protobuf.Timestamp } var file_proto_pbpeering_peering_proto_depIdxs = []int32{ - 35, // 0: peering.Peering.DeletedAt:type_name -> google.protobuf.Timestamp - 28, // 1: peering.Peering.Meta:type_name -> peering.Peering.MetaEntry - 0, // 2: peering.Peering.State:type_name -> peering.PeeringState - 2, // 3: peering.PeeringReadResponse.Peering:type_name -> peering.Peering - 2, // 4: peering.PeeringListResponse.Peerings:type_name -> peering.Peering - 2, // 5: peering.PeeringWriteRequest.Peering:type_name -> peering.Peering - 29, // 6: peering.PeeringWriteRequest.Meta:type_name -> peering.PeeringWriteRequest.MetaEntry - 3, // 7: peering.TrustBundleListByServiceResponse.Bundles:type_name -> peering.PeeringTrustBundle - 3, // 8: peering.TrustBundleReadResponse.Bundle:type_name -> peering.PeeringTrustBundle - 3, // 9: peering.PeeringTrustBundleWriteRequest.PeeringTrustBundle:type_name -> peering.PeeringTrustBundle - 30, // 10: peering.GenerateTokenRequest.Meta:type_name -> peering.GenerateTokenRequest.MetaEntry - 31, // 11: peering.EstablishRequest.Meta:type_name -> peering.EstablishRequest.MetaEntry - 32, // 12: peering.ReplicationMessage.request:type_name -> peering.ReplicationMessage.Request - 33, // 13: peering.ReplicationMessage.response:type_name -> peering.ReplicationMessage.Response - 34, // 14: peering.ReplicationMessage.terminated:type_name -> peering.ReplicationMessage.Terminated - 36, // 15: peering.ReplicationMessage.Request.Error:type_name -> status.Status - 37, // 16: peering.ReplicationMessage.Response.Resource:type_name -> google.protobuf.Any - 1, // 17: peering.ReplicationMessage.Response.operation:type_name -> peering.ReplicationMessage.Response.Operation - 22, // 18: peering.PeeringService.GenerateToken:input_type -> peering.GenerateTokenRequest - 24, // 19: peering.PeeringService.Establish:input_type -> peering.EstablishRequest - 4, // 20: peering.PeeringService.PeeringRead:input_type -> peering.PeeringReadRequest - 6, // 21: peering.PeeringService.PeeringList:input_type -> peering.PeeringListRequest - 10, // 22: peering.PeeringService.PeeringDelete:input_type -> peering.PeeringDeleteRequest - 8, // 23: peering.PeeringService.PeeringWrite:input_type -> peering.PeeringWriteRequest - 12, // 24: peering.PeeringService.TrustBundleListByService:input_type -> peering.TrustBundleListByServiceRequest - 14, // 25: peering.PeeringService.TrustBundleRead:input_type -> peering.TrustBundleReadRequest - 26, // 26: peering.PeeringService.StreamResources:input_type -> peering.ReplicationMessage - 23, // 27: peering.PeeringService.GenerateToken:output_type -> peering.GenerateTokenResponse - 25, // 28: peering.PeeringService.Establish:output_type -> peering.EstablishResponse - 5, // 29: peering.PeeringService.PeeringRead:output_type -> peering.PeeringReadResponse - 7, // 30: peering.PeeringService.PeeringList:output_type -> peering.PeeringListResponse - 11, // 31: peering.PeeringService.PeeringDelete:output_type -> peering.PeeringDeleteResponse - 9, // 32: peering.PeeringService.PeeringWrite:output_type -> peering.PeeringWriteResponse - 13, // 33: peering.PeeringService.TrustBundleListByService:output_type -> peering.TrustBundleListByServiceResponse - 15, // 34: peering.PeeringService.TrustBundleRead:output_type -> peering.TrustBundleReadResponse - 26, // 35: peering.PeeringService.StreamResources:output_type -> peering.ReplicationMessage - 27, // [27:36] is the sub-list for method output_type - 18, // [18:27] is the sub-list for method input_type - 18, // [18:18] is the sub-list for extension type_name - 18, // [18:18] is the sub-list for extension extendee - 0, // [0:18] is the sub-list for field type_name + 29, // 0: hashicorp.consul.internal.peering.Peering.DeletedAt:type_name -> google.protobuf.Timestamp + 25, // 1: hashicorp.consul.internal.peering.Peering.Meta:type_name -> hashicorp.consul.internal.peering.Peering.MetaEntry + 0, // 2: hashicorp.consul.internal.peering.Peering.State:type_name -> hashicorp.consul.internal.peering.PeeringState + 1, // 3: hashicorp.consul.internal.peering.PeeringReadResponse.Peering:type_name -> hashicorp.consul.internal.peering.Peering + 1, // 4: hashicorp.consul.internal.peering.PeeringListResponse.Peerings:type_name -> hashicorp.consul.internal.peering.Peering + 1, // 5: hashicorp.consul.internal.peering.PeeringWriteRequest.Peering:type_name -> hashicorp.consul.internal.peering.Peering + 26, // 6: hashicorp.consul.internal.peering.PeeringWriteRequest.Meta:type_name -> hashicorp.consul.internal.peering.PeeringWriteRequest.MetaEntry + 2, // 7: hashicorp.consul.internal.peering.TrustBundleListByServiceResponse.Bundles:type_name -> hashicorp.consul.internal.peering.PeeringTrustBundle + 2, // 8: hashicorp.consul.internal.peering.TrustBundleReadResponse.Bundle:type_name -> hashicorp.consul.internal.peering.PeeringTrustBundle + 2, // 9: hashicorp.consul.internal.peering.PeeringTrustBundleWriteRequest.PeeringTrustBundle:type_name -> hashicorp.consul.internal.peering.PeeringTrustBundle + 27, // 10: hashicorp.consul.internal.peering.GenerateTokenRequest.Meta:type_name -> hashicorp.consul.internal.peering.GenerateTokenRequest.MetaEntry + 28, // 11: hashicorp.consul.internal.peering.EstablishRequest.Meta:type_name -> hashicorp.consul.internal.peering.EstablishRequest.MetaEntry + 21, // 12: hashicorp.consul.internal.peering.PeeringService.GenerateToken:input_type -> hashicorp.consul.internal.peering.GenerateTokenRequest + 23, // 13: hashicorp.consul.internal.peering.PeeringService.Establish:input_type -> hashicorp.consul.internal.peering.EstablishRequest + 3, // 14: hashicorp.consul.internal.peering.PeeringService.PeeringRead:input_type -> hashicorp.consul.internal.peering.PeeringReadRequest + 5, // 15: hashicorp.consul.internal.peering.PeeringService.PeeringList:input_type -> hashicorp.consul.internal.peering.PeeringListRequest + 9, // 16: hashicorp.consul.internal.peering.PeeringService.PeeringDelete:input_type -> hashicorp.consul.internal.peering.PeeringDeleteRequest + 7, // 17: hashicorp.consul.internal.peering.PeeringService.PeeringWrite:input_type -> hashicorp.consul.internal.peering.PeeringWriteRequest + 11, // 18: hashicorp.consul.internal.peering.PeeringService.TrustBundleListByService:input_type -> hashicorp.consul.internal.peering.TrustBundleListByServiceRequest + 13, // 19: hashicorp.consul.internal.peering.PeeringService.TrustBundleRead:input_type -> hashicorp.consul.internal.peering.TrustBundleReadRequest + 22, // 20: hashicorp.consul.internal.peering.PeeringService.GenerateToken:output_type -> hashicorp.consul.internal.peering.GenerateTokenResponse + 24, // 21: hashicorp.consul.internal.peering.PeeringService.Establish:output_type -> hashicorp.consul.internal.peering.EstablishResponse + 4, // 22: hashicorp.consul.internal.peering.PeeringService.PeeringRead:output_type -> hashicorp.consul.internal.peering.PeeringReadResponse + 6, // 23: hashicorp.consul.internal.peering.PeeringService.PeeringList:output_type -> hashicorp.consul.internal.peering.PeeringListResponse + 10, // 24: hashicorp.consul.internal.peering.PeeringService.PeeringDelete:output_type -> hashicorp.consul.internal.peering.PeeringDeleteResponse + 8, // 25: hashicorp.consul.internal.peering.PeeringService.PeeringWrite:output_type -> hashicorp.consul.internal.peering.PeeringWriteResponse + 12, // 26: hashicorp.consul.internal.peering.PeeringService.TrustBundleListByService:output_type -> hashicorp.consul.internal.peering.TrustBundleListByServiceResponse + 14, // 27: hashicorp.consul.internal.peering.PeeringService.TrustBundleRead:output_type -> hashicorp.consul.internal.peering.TrustBundleReadResponse + 20, // [20:28] is the sub-list for method output_type + 12, // [12:20] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_proto_pbpeering_peering_proto_init() } @@ -2741,79 +2321,14 @@ func file_proto_pbpeering_peering_proto_init() { return nil } } - file_proto_pbpeering_peering_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReplicationMessage); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_pbpeering_peering_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LeaderAddress); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_pbpeering_peering_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReplicationMessage_Request); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_pbpeering_peering_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReplicationMessage_Response); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proto_pbpeering_peering_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReplicationMessage_Terminated); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_proto_pbpeering_peering_proto_msgTypes[24].OneofWrappers = []interface{}{ - (*ReplicationMessage_Request_)(nil), - (*ReplicationMessage_Response_)(nil), - (*ReplicationMessage_Terminated_)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_pbpeering_peering_proto_rawDesc, - NumEnums: 2, - NumMessages: 33, + NumEnums: 1, + NumMessages: 28, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/pbpeering/peering.proto b/proto/pbpeering/peering.proto index 3e5d2397fc..62679bbca1 100644 --- a/proto/pbpeering/peering.proto +++ b/proto/pbpeering/peering.proto @@ -1,11 +1,8 @@ syntax = "proto3"; -package peering; +package hashicorp.consul.internal.peering; import "google/protobuf/timestamp.proto"; -import "google/protobuf/any.proto"; -// TODO(peering): Handle this some other way -import "proto/pbstatus/status.proto"; // PeeringService handles operations for establishing peering relationships // between disparate Consul clusters. @@ -24,13 +21,6 @@ service PeeringService { rpc TrustBundleListByService(TrustBundleListByServiceRequest) returns (TrustBundleListByServiceResponse); rpc TrustBundleRead(TrustBundleReadRequest) returns (TrustBundleReadResponse); - - // StreamResources opens an event stream for resources to share between peers, such as services. - // Events are streamed as they happen. - // buf:lint:ignore RPC_REQUEST_STANDARD_NAME - // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME - // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE - rpc StreamResources(stream ReplicationMessage) returns (stream ReplicationMessage); } // PeeringState enumerates all the states a peering can be in @@ -328,73 +318,3 @@ message EstablishRequest { // output=peering.gen.go // name=API message EstablishResponse {} - -message ReplicationMessage { - oneof Payload { - Request request = 1; - Response response = 2; - Terminated terminated = 3; - } - - // A Request requests to subscribe to a resource of a given type. - message Request { - // An identifier for the peer making the request. - // This identifier is provisioned by the serving peer prior to the request from the dialing peer. - string PeerID = 1; - - // Nonce corresponding to that of the response being ACKed or NACKed. - // Initial subscription requests will have an empty nonce. - // The nonce is generated and incremented by the exporting peer. - string Nonce = 2; - - // The type URL for the resource being requested or ACK/NACKed. - string ResourceURL = 3; - - // The error if the previous response was not applied successfully. - // This field is empty in the first subscription request. - status.Status Error = 4; - } - - // A Response contains resources corresponding to a subscription request. - message Response { - // Nonce identifying a response in a stream. - string Nonce = 1; - - // The type URL of resource being returned. - string ResourceURL = 2; - - // An identifier for the resource being returned. - // This could be the SPIFFE ID of the service. - string ResourceID = 3; - - // The resource being returned. - google.protobuf.Any Resource = 4; - - // Operation enumerates supported operations for replicated resources. - enum Operation { - Unknown = 0; - - // UPSERT represents a create or update event. - UPSERT = 1; - - // DELETE indicates the resource should be deleted. - // In DELETE operations no Resource will be returned. - // Deletion by an importing peer must be done with the type URL and ID. - DELETE = 2; - } - - // REQUIRED. The operation to be performed in relation to the resource. - Operation operation = 5; - } - - // Terminated is sent when a peering is deleted locally. - // This message signals to the peer that they should clean up their local state about the peering. - message Terminated {} -} - -// LeaderAddress is sent when the peering service runs on a consul node -// that is not a leader. The node either lost leadership, or never was a leader. -message LeaderAddress { - // address is an ip:port best effort hint at what could be the cluster leader's address - string address = 1; -} diff --git a/proto/pbpeering/peering_grpc.pb.go b/proto/pbpeering/peering_grpc.pb.go index fb987fa28c..0eb3c734a8 100644 --- a/proto/pbpeering/peering_grpc.pb.go +++ b/proto/pbpeering/peering_grpc.pb.go @@ -33,12 +33,6 @@ type PeeringServiceClient interface { // TODO(peering): Rename this to PeeredServiceRoots? or something like that? TrustBundleListByService(ctx context.Context, in *TrustBundleListByServiceRequest, opts ...grpc.CallOption) (*TrustBundleListByServiceResponse, error) TrustBundleRead(ctx context.Context, in *TrustBundleReadRequest, opts ...grpc.CallOption) (*TrustBundleReadResponse, error) - // StreamResources opens an event stream for resources to share between peers, such as services. - // Events are streamed as they happen. - // buf:lint:ignore RPC_REQUEST_STANDARD_NAME - // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME - // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE - StreamResources(ctx context.Context, opts ...grpc.CallOption) (PeeringService_StreamResourcesClient, error) } type peeringServiceClient struct { @@ -51,7 +45,7 @@ func NewPeeringServiceClient(cc grpc.ClientConnInterface) PeeringServiceClient { func (c *peeringServiceClient) GenerateToken(ctx context.Context, in *GenerateTokenRequest, opts ...grpc.CallOption) (*GenerateTokenResponse, error) { out := new(GenerateTokenResponse) - err := c.cc.Invoke(ctx, "/peering.PeeringService/GenerateToken", in, out, opts...) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.peering.PeeringService/GenerateToken", in, out, opts...) if err != nil { return nil, err } @@ -60,7 +54,7 @@ func (c *peeringServiceClient) GenerateToken(ctx context.Context, in *GenerateTo func (c *peeringServiceClient) Establish(ctx context.Context, in *EstablishRequest, opts ...grpc.CallOption) (*EstablishResponse, error) { out := new(EstablishResponse) - err := c.cc.Invoke(ctx, "/peering.PeeringService/Establish", in, out, opts...) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.peering.PeeringService/Establish", in, out, opts...) if err != nil { return nil, err } @@ -69,7 +63,7 @@ func (c *peeringServiceClient) Establish(ctx context.Context, in *EstablishReque func (c *peeringServiceClient) PeeringRead(ctx context.Context, in *PeeringReadRequest, opts ...grpc.CallOption) (*PeeringReadResponse, error) { out := new(PeeringReadResponse) - err := c.cc.Invoke(ctx, "/peering.PeeringService/PeeringRead", in, out, opts...) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.peering.PeeringService/PeeringRead", in, out, opts...) if err != nil { return nil, err } @@ -78,7 +72,7 @@ func (c *peeringServiceClient) PeeringRead(ctx context.Context, in *PeeringReadR func (c *peeringServiceClient) PeeringList(ctx context.Context, in *PeeringListRequest, opts ...grpc.CallOption) (*PeeringListResponse, error) { out := new(PeeringListResponse) - err := c.cc.Invoke(ctx, "/peering.PeeringService/PeeringList", in, out, opts...) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.peering.PeeringService/PeeringList", in, out, opts...) if err != nil { return nil, err } @@ -87,7 +81,7 @@ func (c *peeringServiceClient) PeeringList(ctx context.Context, in *PeeringListR func (c *peeringServiceClient) PeeringDelete(ctx context.Context, in *PeeringDeleteRequest, opts ...grpc.CallOption) (*PeeringDeleteResponse, error) { out := new(PeeringDeleteResponse) - err := c.cc.Invoke(ctx, "/peering.PeeringService/PeeringDelete", in, out, opts...) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.peering.PeeringService/PeeringDelete", in, out, opts...) if err != nil { return nil, err } @@ -96,7 +90,7 @@ func (c *peeringServiceClient) PeeringDelete(ctx context.Context, in *PeeringDel func (c *peeringServiceClient) PeeringWrite(ctx context.Context, in *PeeringWriteRequest, opts ...grpc.CallOption) (*PeeringWriteResponse, error) { out := new(PeeringWriteResponse) - err := c.cc.Invoke(ctx, "/peering.PeeringService/PeeringWrite", in, out, opts...) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.peering.PeeringService/PeeringWrite", in, out, opts...) if err != nil { return nil, err } @@ -105,7 +99,7 @@ func (c *peeringServiceClient) PeeringWrite(ctx context.Context, in *PeeringWrit func (c *peeringServiceClient) TrustBundleListByService(ctx context.Context, in *TrustBundleListByServiceRequest, opts ...grpc.CallOption) (*TrustBundleListByServiceResponse, error) { out := new(TrustBundleListByServiceResponse) - err := c.cc.Invoke(ctx, "/peering.PeeringService/TrustBundleListByService", in, out, opts...) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.peering.PeeringService/TrustBundleListByService", in, out, opts...) if err != nil { return nil, err } @@ -114,44 +108,13 @@ func (c *peeringServiceClient) TrustBundleListByService(ctx context.Context, in func (c *peeringServiceClient) TrustBundleRead(ctx context.Context, in *TrustBundleReadRequest, opts ...grpc.CallOption) (*TrustBundleReadResponse, error) { out := new(TrustBundleReadResponse) - err := c.cc.Invoke(ctx, "/peering.PeeringService/TrustBundleRead", in, out, opts...) + err := c.cc.Invoke(ctx, "/hashicorp.consul.internal.peering.PeeringService/TrustBundleRead", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *peeringServiceClient) StreamResources(ctx context.Context, opts ...grpc.CallOption) (PeeringService_StreamResourcesClient, error) { - stream, err := c.cc.NewStream(ctx, &PeeringService_ServiceDesc.Streams[0], "/peering.PeeringService/StreamResources", opts...) - if err != nil { - return nil, err - } - x := &peeringServiceStreamResourcesClient{stream} - return x, nil -} - -type PeeringService_StreamResourcesClient interface { - Send(*ReplicationMessage) error - Recv() (*ReplicationMessage, error) - grpc.ClientStream -} - -type peeringServiceStreamResourcesClient struct { - grpc.ClientStream -} - -func (x *peeringServiceStreamResourcesClient) Send(m *ReplicationMessage) error { - return x.ClientStream.SendMsg(m) -} - -func (x *peeringServiceStreamResourcesClient) Recv() (*ReplicationMessage, error) { - m := new(ReplicationMessage) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - // PeeringServiceServer is the server API for PeeringService service. // All implementations should embed UnimplementedPeeringServiceServer // for forward compatibility @@ -167,12 +130,6 @@ type PeeringServiceServer interface { // TODO(peering): Rename this to PeeredServiceRoots? or something like that? TrustBundleListByService(context.Context, *TrustBundleListByServiceRequest) (*TrustBundleListByServiceResponse, error) TrustBundleRead(context.Context, *TrustBundleReadRequest) (*TrustBundleReadResponse, error) - // StreamResources opens an event stream for resources to share between peers, such as services. - // Events are streamed as they happen. - // buf:lint:ignore RPC_REQUEST_STANDARD_NAME - // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME - // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE - StreamResources(PeeringService_StreamResourcesServer) error } // UnimplementedPeeringServiceServer should be embedded to have forward compatible implementations. @@ -203,9 +160,6 @@ func (UnimplementedPeeringServiceServer) TrustBundleListByService(context.Contex func (UnimplementedPeeringServiceServer) TrustBundleRead(context.Context, *TrustBundleReadRequest) (*TrustBundleReadResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method TrustBundleRead not implemented") } -func (UnimplementedPeeringServiceServer) StreamResources(PeeringService_StreamResourcesServer) error { - return status.Errorf(codes.Unimplemented, "method StreamResources not implemented") -} // UnsafePeeringServiceServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to PeeringServiceServer will @@ -228,7 +182,7 @@ func _PeeringService_GenerateToken_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/peering.PeeringService/GenerateToken", + FullMethod: "/hashicorp.consul.internal.peering.PeeringService/GenerateToken", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(PeeringServiceServer).GenerateToken(ctx, req.(*GenerateTokenRequest)) @@ -246,7 +200,7 @@ func _PeeringService_Establish_Handler(srv interface{}, ctx context.Context, dec } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/peering.PeeringService/Establish", + FullMethod: "/hashicorp.consul.internal.peering.PeeringService/Establish", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(PeeringServiceServer).Establish(ctx, req.(*EstablishRequest)) @@ -264,7 +218,7 @@ func _PeeringService_PeeringRead_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/peering.PeeringService/PeeringRead", + FullMethod: "/hashicorp.consul.internal.peering.PeeringService/PeeringRead", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(PeeringServiceServer).PeeringRead(ctx, req.(*PeeringReadRequest)) @@ -282,7 +236,7 @@ func _PeeringService_PeeringList_Handler(srv interface{}, ctx context.Context, d } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/peering.PeeringService/PeeringList", + FullMethod: "/hashicorp.consul.internal.peering.PeeringService/PeeringList", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(PeeringServiceServer).PeeringList(ctx, req.(*PeeringListRequest)) @@ -300,7 +254,7 @@ func _PeeringService_PeeringDelete_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/peering.PeeringService/PeeringDelete", + FullMethod: "/hashicorp.consul.internal.peering.PeeringService/PeeringDelete", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(PeeringServiceServer).PeeringDelete(ctx, req.(*PeeringDeleteRequest)) @@ -318,7 +272,7 @@ func _PeeringService_PeeringWrite_Handler(srv interface{}, ctx context.Context, } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/peering.PeeringService/PeeringWrite", + FullMethod: "/hashicorp.consul.internal.peering.PeeringService/PeeringWrite", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(PeeringServiceServer).PeeringWrite(ctx, req.(*PeeringWriteRequest)) @@ -336,7 +290,7 @@ func _PeeringService_TrustBundleListByService_Handler(srv interface{}, ctx conte } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/peering.PeeringService/TrustBundleListByService", + FullMethod: "/hashicorp.consul.internal.peering.PeeringService/TrustBundleListByService", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(PeeringServiceServer).TrustBundleListByService(ctx, req.(*TrustBundleListByServiceRequest)) @@ -354,7 +308,7 @@ func _PeeringService_TrustBundleRead_Handler(srv interface{}, ctx context.Contex } info := &grpc.UnaryServerInfo{ Server: srv, - FullMethod: "/peering.PeeringService/TrustBundleRead", + FullMethod: "/hashicorp.consul.internal.peering.PeeringService/TrustBundleRead", } handler := func(ctx context.Context, req interface{}) (interface{}, error) { return srv.(PeeringServiceServer).TrustBundleRead(ctx, req.(*TrustBundleReadRequest)) @@ -362,37 +316,11 @@ func _PeeringService_TrustBundleRead_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } -func _PeeringService_StreamResources_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(PeeringServiceServer).StreamResources(&peeringServiceStreamResourcesServer{stream}) -} - -type PeeringService_StreamResourcesServer interface { - Send(*ReplicationMessage) error - Recv() (*ReplicationMessage, error) - grpc.ServerStream -} - -type peeringServiceStreamResourcesServer struct { - grpc.ServerStream -} - -func (x *peeringServiceStreamResourcesServer) Send(m *ReplicationMessage) error { - return x.ServerStream.SendMsg(m) -} - -func (x *peeringServiceStreamResourcesServer) Recv() (*ReplicationMessage, error) { - m := new(ReplicationMessage) - if err := x.ServerStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - // PeeringService_ServiceDesc is the grpc.ServiceDesc for PeeringService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) var PeeringService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "peering.PeeringService", + ServiceName: "hashicorp.consul.internal.peering.PeeringService", HandlerType: (*PeeringServiceServer)(nil), Methods: []grpc.MethodDesc{ { @@ -428,13 +356,6 @@ var PeeringService_ServiceDesc = grpc.ServiceDesc{ Handler: _PeeringService_TrustBundleRead_Handler, }, }, - Streams: []grpc.StreamDesc{ - { - StreamName: "StreamResources", - Handler: _PeeringService_StreamResources_Handler, - ServerStreams: true, - ClientStreams: true, - }, - }, + Streams: []grpc.StreamDesc{}, Metadata: "proto/pbpeering/peering.proto", } diff --git a/proto/pbpeerstream/peerstream.go b/proto/pbpeerstream/peerstream.go new file mode 100644 index 0000000000..00bd690ae1 --- /dev/null +++ b/proto/pbpeerstream/peerstream.go @@ -0,0 +1,5 @@ +package pbpeerstream + +func (x Operation) GoString() string { + return x.String() +} diff --git a/proto/pbpeerstream/peerstream.pb.binary.go b/proto/pbpeerstream/peerstream.pb.binary.go new file mode 100644 index 0000000000..39dbdb8141 --- /dev/null +++ b/proto/pbpeerstream/peerstream.pb.binary.go @@ -0,0 +1,58 @@ +// Code generated by protoc-gen-go-binary. DO NOT EDIT. +// source: proto/pbpeerstream/peerstream.proto + +package pbpeerstream + +import ( + "github.com/golang/protobuf/proto" +) + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ReplicationMessage) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ReplicationMessage) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ReplicationMessage_Request) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ReplicationMessage_Request) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ReplicationMessage_Response) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ReplicationMessage_Response) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ReplicationMessage_Terminated) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ReplicationMessage_Terminated) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *LeaderAddress) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *LeaderAddress) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto/pbpeerstream/peerstream.pb.go b/proto/pbpeerstream/peerstream.pb.go new file mode 100644 index 0000000000..e9da9cc56f --- /dev/null +++ b/proto/pbpeerstream/peerstream.pb.go @@ -0,0 +1,658 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0-rc.1 +// protoc (unknown) +// source: proto/pbpeerstream/peerstream.proto + +package pbpeerstream + +import ( + pbstatus "github.com/hashicorp/consul/proto/pbstatus" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + anypb "google.golang.org/protobuf/types/known/anypb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Operation enumerates supported operations for replicated resources. +type Operation int32 + +const ( + Operation_OPERATION_UNSPECIFIED Operation = 0 + // UPSERT represents a create or update event. + Operation_OPERATION_UPSERT Operation = 1 + // DELETE indicates the resource should be deleted. + // In DELETE operations no Resource will be returned. + // Deletion by an importing peer must be done with the type URL and ID. + Operation_OPERATION_DELETE Operation = 2 +) + +// Enum value maps for Operation. +var ( + Operation_name = map[int32]string{ + 0: "OPERATION_UNSPECIFIED", + 1: "OPERATION_UPSERT", + 2: "OPERATION_DELETE", + } + Operation_value = map[string]int32{ + "OPERATION_UNSPECIFIED": 0, + "OPERATION_UPSERT": 1, + "OPERATION_DELETE": 2, + } +) + +func (x Operation) Enum() *Operation { + p := new(Operation) + *p = x + return p +} + +func (x Operation) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Operation) Descriptor() protoreflect.EnumDescriptor { + return file_proto_pbpeerstream_peerstream_proto_enumTypes[0].Descriptor() +} + +func (Operation) Type() protoreflect.EnumType { + return &file_proto_pbpeerstream_peerstream_proto_enumTypes[0] +} + +func (x Operation) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Operation.Descriptor instead. +func (Operation) EnumDescriptor() ([]byte, []int) { + return file_proto_pbpeerstream_peerstream_proto_rawDescGZIP(), []int{0} +} + +type ReplicationMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Payload: + // *ReplicationMessage_Request_ + // *ReplicationMessage_Response_ + // *ReplicationMessage_Terminated_ + Payload isReplicationMessage_Payload `protobuf_oneof:"Payload"` +} + +func (x *ReplicationMessage) Reset() { + *x = ReplicationMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReplicationMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReplicationMessage) ProtoMessage() {} + +func (x *ReplicationMessage) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReplicationMessage.ProtoReflect.Descriptor instead. +func (*ReplicationMessage) Descriptor() ([]byte, []int) { + return file_proto_pbpeerstream_peerstream_proto_rawDescGZIP(), []int{0} +} + +func (m *ReplicationMessage) GetPayload() isReplicationMessage_Payload { + if m != nil { + return m.Payload + } + return nil +} + +func (x *ReplicationMessage) GetRequest() *ReplicationMessage_Request { + if x, ok := x.GetPayload().(*ReplicationMessage_Request_); ok { + return x.Request + } + return nil +} + +func (x *ReplicationMessage) GetResponse() *ReplicationMessage_Response { + if x, ok := x.GetPayload().(*ReplicationMessage_Response_); ok { + return x.Response + } + return nil +} + +func (x *ReplicationMessage) GetTerminated() *ReplicationMessage_Terminated { + if x, ok := x.GetPayload().(*ReplicationMessage_Terminated_); ok { + return x.Terminated + } + return nil +} + +type isReplicationMessage_Payload interface { + isReplicationMessage_Payload() +} + +type ReplicationMessage_Request_ struct { + Request *ReplicationMessage_Request `protobuf:"bytes,1,opt,name=request,proto3,oneof"` +} + +type ReplicationMessage_Response_ struct { + Response *ReplicationMessage_Response `protobuf:"bytes,2,opt,name=response,proto3,oneof"` +} + +type ReplicationMessage_Terminated_ struct { + Terminated *ReplicationMessage_Terminated `protobuf:"bytes,3,opt,name=terminated,proto3,oneof"` +} + +func (*ReplicationMessage_Request_) isReplicationMessage_Payload() {} + +func (*ReplicationMessage_Response_) isReplicationMessage_Payload() {} + +func (*ReplicationMessage_Terminated_) isReplicationMessage_Payload() {} + +// LeaderAddress is sent when the peering service runs on a consul node +// that is not a leader. The node either lost leadership, or never was a leader. +type LeaderAddress struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // address is an ip:port best effort hint at what could be the cluster leader's address + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (x *LeaderAddress) Reset() { + *x = LeaderAddress{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *LeaderAddress) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*LeaderAddress) ProtoMessage() {} + +func (x *LeaderAddress) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use LeaderAddress.ProtoReflect.Descriptor instead. +func (*LeaderAddress) Descriptor() ([]byte, []int) { + return file_proto_pbpeerstream_peerstream_proto_rawDescGZIP(), []int{1} +} + +func (x *LeaderAddress) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +// A Request requests to subscribe to a resource of a given type. +type ReplicationMessage_Request struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // An identifier for the peer making the request. + // This identifier is provisioned by the serving peer prior to the request from the dialing peer. + PeerID string `protobuf:"bytes,1,opt,name=PeerID,proto3" json:"PeerID,omitempty"` + // ResponseNonce corresponding to that of the response being ACKed or NACKed. + // Initial subscription requests will have an empty nonce. + // The nonce is generated and incremented by the exporting peer. + // TODO + ResponseNonce string `protobuf:"bytes,2,opt,name=ResponseNonce,proto3" json:"ResponseNonce,omitempty"` + // The type URL for the resource being requested or ACK/NACKed. + ResourceURL string `protobuf:"bytes,3,opt,name=ResourceURL,proto3" json:"ResourceURL,omitempty"` + // The error if the previous response was not applied successfully. + // This field is empty in the first subscription request. + Error *pbstatus.Status `protobuf:"bytes,4,opt,name=Error,proto3" json:"Error,omitempty"` +} + +func (x *ReplicationMessage_Request) Reset() { + *x = ReplicationMessage_Request{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReplicationMessage_Request) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReplicationMessage_Request) ProtoMessage() {} + +func (x *ReplicationMessage_Request) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReplicationMessage_Request.ProtoReflect.Descriptor instead. +func (*ReplicationMessage_Request) Descriptor() ([]byte, []int) { + return file_proto_pbpeerstream_peerstream_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *ReplicationMessage_Request) GetPeerID() string { + if x != nil { + return x.PeerID + } + return "" +} + +func (x *ReplicationMessage_Request) GetResponseNonce() string { + if x != nil { + return x.ResponseNonce + } + return "" +} + +func (x *ReplicationMessage_Request) GetResourceURL() string { + if x != nil { + return x.ResourceURL + } + return "" +} + +func (x *ReplicationMessage_Request) GetError() *pbstatus.Status { + if x != nil { + return x.Error + } + return nil +} + +// A Response contains resources corresponding to a subscription request. +type ReplicationMessage_Response struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Nonce identifying a response in a stream. + Nonce string `protobuf:"bytes,1,opt,name=Nonce,proto3" json:"Nonce,omitempty"` + // The type URL of resource being returned. + ResourceURL string `protobuf:"bytes,2,opt,name=ResourceURL,proto3" json:"ResourceURL,omitempty"` + // An identifier for the resource being returned. + // This could be the SPIFFE ID of the service. + ResourceID string `protobuf:"bytes,3,opt,name=ResourceID,proto3" json:"ResourceID,omitempty"` + // The resource being returned. + Resource *anypb.Any `protobuf:"bytes,4,opt,name=Resource,proto3" json:"Resource,omitempty"` + // REQUIRED. The operation to be performed in relation to the resource. + Operation Operation `protobuf:"varint,5,opt,name=operation,proto3,enum=hashicorp.consul.internal.peerstream.Operation" json:"operation,omitempty"` +} + +func (x *ReplicationMessage_Response) Reset() { + *x = ReplicationMessage_Response{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReplicationMessage_Response) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReplicationMessage_Response) ProtoMessage() {} + +func (x *ReplicationMessage_Response) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReplicationMessage_Response.ProtoReflect.Descriptor instead. +func (*ReplicationMessage_Response) Descriptor() ([]byte, []int) { + return file_proto_pbpeerstream_peerstream_proto_rawDescGZIP(), []int{0, 1} +} + +func (x *ReplicationMessage_Response) GetNonce() string { + if x != nil { + return x.Nonce + } + return "" +} + +func (x *ReplicationMessage_Response) GetResourceURL() string { + if x != nil { + return x.ResourceURL + } + return "" +} + +func (x *ReplicationMessage_Response) GetResourceID() string { + if x != nil { + return x.ResourceID + } + return "" +} + +func (x *ReplicationMessage_Response) GetResource() *anypb.Any { + if x != nil { + return x.Resource + } + return nil +} + +func (x *ReplicationMessage_Response) GetOperation() Operation { + if x != nil { + return x.Operation + } + return Operation_OPERATION_UNSPECIFIED +} + +// Terminated is sent when a peering is deleted locally. +// This message signals to the peer that they should clean up their local state about the peering. +type ReplicationMessage_Terminated struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ReplicationMessage_Terminated) Reset() { + *x = ReplicationMessage_Terminated{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReplicationMessage_Terminated) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReplicationMessage_Terminated) ProtoMessage() {} + +func (x *ReplicationMessage_Terminated) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbpeerstream_peerstream_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReplicationMessage_Terminated.ProtoReflect.Descriptor instead. +func (*ReplicationMessage_Terminated) Descriptor() ([]byte, []int) { + return file_proto_pbpeerstream_peerstream_proto_rawDescGZIP(), []int{0, 2} +} + +var File_proto_pbpeerstream_peerstream_proto protoreflect.FileDescriptor + +var file_proto_pbpeerstream_peerstream_proto_rawDesc = []byte{ + 0x0a, 0x23, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x70, 0x65, 0x65, 0x72, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x2f, 0x70, 0x65, 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x24, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x1a, 0x19, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0xe5, 0x05, 0x0a, 0x12, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x5c, 0x0a, 0x07, 0x72, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, + 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5f, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 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, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, + 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0a, 0x74, 0x65, 0x72, + 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x43, 0x2e, + 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, + 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, + 0x65, 0x64, 0x48, 0x00, 0x52, 0x0a, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, + 0x1a, 0xa9, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, + 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x65, + 0x65, 0x72, 0x49, 0x44, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x12, 0x3e, 0x0a, 0x05, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 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, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x1a, 0xe3, 0x01, 0x0a, + 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x6e, + 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x12, + 0x20, 0x0a, 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x52, 0x4c, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x52, + 0x4c, 0x12, 0x1e, 0x0a, 0x0a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x44, 0x12, 0x30, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x4d, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x4f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x1a, 0x0c, 0x0a, 0x0a, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, + 0x42, 0x09, 0x0a, 0x07, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x29, 0x0a, 0x0d, 0x4c, + 0x65, 0x61, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2a, 0x52, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, + 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x55, 0x50, 0x53, 0x45, + 0x52, 0x54, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x4f, 0x50, 0x45, 0x52, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x32, 0x9f, 0x01, 0x0a, 0x11, 0x50, + 0x65, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x89, 0x01, 0x0a, 0x0f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x12, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x52, 0x65, 0x70, 0x6c, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 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, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x9f, 0x02, 0x0a, + 0x28, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, + 0x65, 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x0f, 0x50, 0x65, 0x65, 0x72, 0x73, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2e, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xa2, 0x02, 0x04, 0x48, + 0x43, 0x49, 0x50, 0xaa, 0x02, 0x24, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0xca, 0x02, 0x24, 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, 0x73, 0x74, 0x72, 0x65, 0x61, + 0x6d, 0xe2, 0x02, 0x30, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x27, 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, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_pbpeerstream_peerstream_proto_rawDescOnce sync.Once + file_proto_pbpeerstream_peerstream_proto_rawDescData = file_proto_pbpeerstream_peerstream_proto_rawDesc +) + +func file_proto_pbpeerstream_peerstream_proto_rawDescGZIP() []byte { + file_proto_pbpeerstream_peerstream_proto_rawDescOnce.Do(func() { + file_proto_pbpeerstream_peerstream_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_pbpeerstream_peerstream_proto_rawDescData) + }) + return file_proto_pbpeerstream_peerstream_proto_rawDescData +} + +var file_proto_pbpeerstream_peerstream_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_proto_pbpeerstream_peerstream_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_proto_pbpeerstream_peerstream_proto_goTypes = []interface{}{ + (Operation)(0), // 0: hashicorp.consul.internal.peerstream.Operation + (*ReplicationMessage)(nil), // 1: hashicorp.consul.internal.peerstream.ReplicationMessage + (*LeaderAddress)(nil), // 2: hashicorp.consul.internal.peerstream.LeaderAddress + (*ReplicationMessage_Request)(nil), // 3: hashicorp.consul.internal.peerstream.ReplicationMessage.Request + (*ReplicationMessage_Response)(nil), // 4: hashicorp.consul.internal.peerstream.ReplicationMessage.Response + (*ReplicationMessage_Terminated)(nil), // 5: hashicorp.consul.internal.peerstream.ReplicationMessage.Terminated + (*pbstatus.Status)(nil), // 6: hashicorp.consul.internal.status.Status + (*anypb.Any)(nil), // 7: google.protobuf.Any +} +var file_proto_pbpeerstream_peerstream_proto_depIdxs = []int32{ + 3, // 0: hashicorp.consul.internal.peerstream.ReplicationMessage.request:type_name -> hashicorp.consul.internal.peerstream.ReplicationMessage.Request + 4, // 1: hashicorp.consul.internal.peerstream.ReplicationMessage.response:type_name -> hashicorp.consul.internal.peerstream.ReplicationMessage.Response + 5, // 2: hashicorp.consul.internal.peerstream.ReplicationMessage.terminated:type_name -> hashicorp.consul.internal.peerstream.ReplicationMessage.Terminated + 6, // 3: hashicorp.consul.internal.peerstream.ReplicationMessage.Request.Error:type_name -> hashicorp.consul.internal.status.Status + 7, // 4: hashicorp.consul.internal.peerstream.ReplicationMessage.Response.Resource:type_name -> google.protobuf.Any + 0, // 5: hashicorp.consul.internal.peerstream.ReplicationMessage.Response.operation:type_name -> hashicorp.consul.internal.peerstream.Operation + 1, // 6: hashicorp.consul.internal.peerstream.PeerStreamService.StreamResources:input_type -> hashicorp.consul.internal.peerstream.ReplicationMessage + 1, // 7: hashicorp.consul.internal.peerstream.PeerStreamService.StreamResources:output_type -> hashicorp.consul.internal.peerstream.ReplicationMessage + 7, // [7:8] is the sub-list for method output_type + 6, // [6:7] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_proto_pbpeerstream_peerstream_proto_init() } +func file_proto_pbpeerstream_peerstream_proto_init() { + if File_proto_pbpeerstream_peerstream_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_pbpeerstream_peerstream_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReplicationMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbpeerstream_peerstream_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LeaderAddress); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbpeerstream_peerstream_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReplicationMessage_Request); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbpeerstream_peerstream_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReplicationMessage_Response); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbpeerstream_peerstream_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReplicationMessage_Terminated); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_proto_pbpeerstream_peerstream_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*ReplicationMessage_Request_)(nil), + (*ReplicationMessage_Response_)(nil), + (*ReplicationMessage_Terminated_)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_pbpeerstream_peerstream_proto_rawDesc, + NumEnums: 1, + NumMessages: 5, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_proto_pbpeerstream_peerstream_proto_goTypes, + DependencyIndexes: file_proto_pbpeerstream_peerstream_proto_depIdxs, + EnumInfos: file_proto_pbpeerstream_peerstream_proto_enumTypes, + MessageInfos: file_proto_pbpeerstream_peerstream_proto_msgTypes, + }.Build() + File_proto_pbpeerstream_peerstream_proto = out.File + file_proto_pbpeerstream_peerstream_proto_rawDesc = nil + file_proto_pbpeerstream_peerstream_proto_goTypes = nil + file_proto_pbpeerstream_peerstream_proto_depIdxs = nil +} diff --git a/proto/pbpeerstream/peerstream.proto b/proto/pbpeerstream/peerstream.proto new file mode 100644 index 0000000000..ee19a2df71 --- /dev/null +++ b/proto/pbpeerstream/peerstream.proto @@ -0,0 +1,91 @@ +syntax = "proto3"; + +package hashicorp.consul.internal.peerstream; + +import "google/protobuf/any.proto"; +// TODO(peering): Handle this some other way +import "proto/pbstatus/status.proto"; + +// TODO(peering): comments + +// TODO(peering): also duplicate the pbservice, some pbpeering, and ca stuff. + +service PeerStreamService { + // StreamResources opens an event stream for resources to share between peers, such as services. + // Events are streamed as they happen. + // buf:lint:ignore RPC_REQUEST_STANDARD_NAME + // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME + // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE + rpc StreamResources(stream ReplicationMessage) returns (stream ReplicationMessage); +} + +message ReplicationMessage { + oneof Payload { + Request request = 1; + Response response = 2; + Terminated terminated = 3; + } + + // A Request requests to subscribe to a resource of a given type. + message Request { + // An identifier for the peer making the request. + // This identifier is provisioned by the serving peer prior to the request from the dialing peer. + string PeerID = 1; + + // ResponseNonce corresponding to that of the response being ACKed or NACKed. + // Initial subscription requests will have an empty nonce. + // The nonce is generated and incremented by the exporting peer. + // TODO + string ResponseNonce = 2; + + // The type URL for the resource being requested or ACK/NACKed. + string ResourceURL = 3; + + // The error if the previous response was not applied successfully. + // This field is empty in the first subscription request. + status.Status Error = 4; + } + + // A Response contains resources corresponding to a subscription request. + message Response { + // Nonce identifying a response in a stream. + string Nonce = 1; + + // The type URL of resource being returned. + string ResourceURL = 2; + + // An identifier for the resource being returned. + // This could be the SPIFFE ID of the service. + string ResourceID = 3; + + // The resource being returned. + google.protobuf.Any Resource = 4; + + // REQUIRED. The operation to be performed in relation to the resource. + Operation operation = 5; + } + + // Terminated is sent when a peering is deleted locally. + // This message signals to the peer that they should clean up their local state about the peering. + message Terminated {} +} + +// Operation enumerates supported operations for replicated resources. +enum Operation { + OPERATION_UNSPECIFIED = 0; + + // UPSERT represents a create or update event. + OPERATION_UPSERT = 1; + + // DELETE indicates the resource should be deleted. + // In DELETE operations no Resource will be returned. + // Deletion by an importing peer must be done with the type URL and ID. + OPERATION_DELETE = 2; +} + +// LeaderAddress is sent when the peering service runs on a consul node +// that is not a leader. The node either lost leadership, or never was a leader. +message LeaderAddress { + // address is an ip:port best effort hint at what could be the cluster leader's address + string address = 1; +} diff --git a/proto/pbpeerstream/peerstream_grpc.pb.go b/proto/pbpeerstream/peerstream_grpc.pb.go new file mode 100644 index 0000000000..dcaebed92b --- /dev/null +++ b/proto/pbpeerstream/peerstream_grpc.pb.go @@ -0,0 +1,145 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc (unknown) +// source: proto/pbpeerstream/peerstream.proto + +package pbpeerstream + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// PeerStreamServiceClient is the client API for PeerStreamService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type PeerStreamServiceClient interface { + // StreamResources opens an event stream for resources to share between peers, such as services. + // Events are streamed as they happen. + // buf:lint:ignore RPC_REQUEST_STANDARD_NAME + // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME + // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE + StreamResources(ctx context.Context, opts ...grpc.CallOption) (PeerStreamService_StreamResourcesClient, error) +} + +type peerStreamServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewPeerStreamServiceClient(cc grpc.ClientConnInterface) PeerStreamServiceClient { + return &peerStreamServiceClient{cc} +} + +func (c *peerStreamServiceClient) StreamResources(ctx context.Context, opts ...grpc.CallOption) (PeerStreamService_StreamResourcesClient, error) { + stream, err := c.cc.NewStream(ctx, &PeerStreamService_ServiceDesc.Streams[0], "/hashicorp.consul.internal.peerstream.PeerStreamService/StreamResources", opts...) + if err != nil { + return nil, err + } + x := &peerStreamServiceStreamResourcesClient{stream} + return x, nil +} + +type PeerStreamService_StreamResourcesClient interface { + Send(*ReplicationMessage) error + Recv() (*ReplicationMessage, error) + grpc.ClientStream +} + +type peerStreamServiceStreamResourcesClient struct { + grpc.ClientStream +} + +func (x *peerStreamServiceStreamResourcesClient) Send(m *ReplicationMessage) error { + return x.ClientStream.SendMsg(m) +} + +func (x *peerStreamServiceStreamResourcesClient) Recv() (*ReplicationMessage, error) { + m := new(ReplicationMessage) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// PeerStreamServiceServer is the server API for PeerStreamService service. +// All implementations should embed UnimplementedPeerStreamServiceServer +// for forward compatibility +type PeerStreamServiceServer interface { + // StreamResources opens an event stream for resources to share between peers, such as services. + // Events are streamed as they happen. + // buf:lint:ignore RPC_REQUEST_STANDARD_NAME + // buf:lint:ignore RPC_RESPONSE_STANDARD_NAME + // buf:lint:ignore RPC_REQUEST_RESPONSE_UNIQUE + StreamResources(PeerStreamService_StreamResourcesServer) error +} + +// UnimplementedPeerStreamServiceServer should be embedded to have forward compatible implementations. +type UnimplementedPeerStreamServiceServer struct { +} + +func (UnimplementedPeerStreamServiceServer) StreamResources(PeerStreamService_StreamResourcesServer) error { + return status.Errorf(codes.Unimplemented, "method StreamResources not implemented") +} + +// UnsafePeerStreamServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to PeerStreamServiceServer will +// result in compilation errors. +type UnsafePeerStreamServiceServer interface { + mustEmbedUnimplementedPeerStreamServiceServer() +} + +func RegisterPeerStreamServiceServer(s grpc.ServiceRegistrar, srv PeerStreamServiceServer) { + s.RegisterService(&PeerStreamService_ServiceDesc, srv) +} + +func _PeerStreamService_StreamResources_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(PeerStreamServiceServer).StreamResources(&peerStreamServiceStreamResourcesServer{stream}) +} + +type PeerStreamService_StreamResourcesServer interface { + Send(*ReplicationMessage) error + Recv() (*ReplicationMessage, error) + grpc.ServerStream +} + +type peerStreamServiceStreamResourcesServer struct { + grpc.ServerStream +} + +func (x *peerStreamServiceStreamResourcesServer) Send(m *ReplicationMessage) error { + return x.ServerStream.SendMsg(m) +} + +func (x *peerStreamServiceStreamResourcesServer) Recv() (*ReplicationMessage, error) { + m := new(ReplicationMessage) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// PeerStreamService_ServiceDesc is the grpc.ServiceDesc for PeerStreamService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var PeerStreamService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "hashicorp.consul.internal.peerstream.PeerStreamService", + HandlerType: (*PeerStreamServiceServer)(nil), + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "StreamResources", + Handler: _PeerStreamService_StreamResources_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "proto/pbpeerstream/peerstream.proto", +} diff --git a/proto/pbpeering/types.go b/proto/pbpeerstream/types.go similarity index 91% rename from proto/pbpeering/types.go rename to proto/pbpeerstream/types.go index 23847e46e7..52f32487d4 100644 --- a/proto/pbpeering/types.go +++ b/proto/pbpeerstream/types.go @@ -1,4 +1,4 @@ -package pbpeering +package pbpeerstream const ( TypeURLService = "type.googleapis.com/consul.api.Service" diff --git a/proto/pbservice/healthcheck.pb.go b/proto/pbservice/healthcheck.pb.go index 964ee22574..ff05cc67ea 100644 --- a/proto/pbservice/healthcheck.pb.go +++ b/proto/pbservice/healthcheck.pb.go @@ -817,196 +817,218 @@ var File_proto_pbservice_healthcheck_proto protoreflect.FileDescriptor var file_proto_pbservice_healthcheck_proto_rawDesc = []byte{ 0x0a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, 0x1e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb0, 0x04, 0x0a, 0x0b, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x6f, 0x64, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x4f, 0x75, 0x74, - 0x70, 0x75, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x12, - 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, - 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, - 0x61, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x3e, 0x0a, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x44, 0x65, 0x66, - 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, - 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x3e, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, - 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, - 0x73, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x45, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, - 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x11, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x23, 0x0a, 0x0b, - 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x22, 0xc0, 0x07, 0x0a, 0x15, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x48, - 0x54, 0x54, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, - 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, - 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x54, 0x4c, - 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x42, 0x0a, 0x06, 0x48, - 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, - 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x18, - 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x10, 0x44, - 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, - 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x43, 0x50, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x44, 0x50, - 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, 0x35, 0x0a, 0x08, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, - 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x61, 0x0a, - 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, - 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, - 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, - 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x18, 0x0a, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, - 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x44, 0x6f, 0x63, - 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x14, - 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x53, - 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x18, 0x14, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x12, 0x22, 0x0a, 0x0c, - 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x15, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, - 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, 0x73, 0x65, 0x54, - 0x4c, 0x53, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, 0x73, - 0x65, 0x54, 0x4c, 0x53, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, - 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, - 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, 0x11, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, - 0x54, 0x54, 0x4c, 0x1a, 0x4f, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, - 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe2, 0x09, 0x0a, 0x09, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x74, 0x65, - 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x1e, - 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x12, - 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x54, - 0x54, 0x50, 0x12, 0x36, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x14, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, - 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x54, 0x43, 0x50, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x18, 0x20, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, 0x35, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, - 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, - 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x49, 0x44, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x44, 0x6f, 0x63, 0x6b, - 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, - 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x53, 0x68, - 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x18, 0x1c, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x12, 0x22, 0x0a, 0x0c, 0x48, - 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x1e, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, - 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x47, - 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, 0x73, 0x65, 0x54, 0x4c, - 0x53, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, 0x73, 0x65, - 0x54, 0x4c, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, - 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, - 0x33, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, 0x12, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x54, - 0x4c, 0x12, 0x32, 0x0a, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x65, 0x66, 0x6f, - 0x72, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x15, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x50, 0x61, - 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, - 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x1d, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, - 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x12, 0x36, 0x0a, 0x16, 0x46, - 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x43, 0x72, 0x69, - 0x74, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, 0x05, 0x52, 0x16, 0x46, 0x61, 0x69, - 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, - 0x63, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x48, 0x54, 0x54, 0x50, - 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x48, 0x54, 0x54, - 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x47, 0x52, 0x50, 0x43, 0x18, 0x18, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x47, 0x52, 0x50, 0x43, 0x12, + 0x6f, 0x74, 0x6f, 0x12, 0x21, 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, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0xfe, 0x04, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, + 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, + 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, + 0x74, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x54, 0x61, 0x67, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x58, 0x0a, 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0a, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x09, 0x52, + 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, + 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, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, + 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, + 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, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x12, 0x20, 0x0a, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x18, + 0x0e, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x64, 0x50, 0x6f, + 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x0f, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x18, + 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, + 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xf4, 0x07, 0x0a, 0x15, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, + 0x54, 0x4c, 0x53, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, + 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x12, 0x5c, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x44, 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, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x42, 0x6f, 0x64, + 0x79, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, + 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, + 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, 0x50, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x43, 0x50, 0x12, 0x10, 0x0a, 0x03, 0x55, + 0x44, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, 0x35, 0x0a, + 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, + 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x4f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x54, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, - 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, - 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, - 0x69, 0x7a, 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, - 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x4f, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, - 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, + 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, + 0x67, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x44, + 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, + 0x12, 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, + 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, 0x47, 0x12, 0x22, + 0x0a, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x15, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, + 0x4c, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, 0x43, 0x55, 0x73, + 0x65, 0x54, 0x4c, 0x53, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, 0x52, 0x50, 0x43, + 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, + 0x6f, 0x64, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, 0x4c, 0x18, + 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x03, 0x54, 0x54, 0x4c, 0x1a, 0x69, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0x96, 0x0a, 0x0a, 0x09, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x48, 0x54, + 0x54, 0x50, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x54, 0x54, 0x50, 0x12, 0x50, + 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x2e, 0x48, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, + 0x12, 0x16, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x42, 0x6f, 0x64, 0x79, + 0x18, 0x1a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x42, 0x6f, 0x64, 0x79, 0x12, 0x2a, 0x0a, 0x10, + 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, + 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x52, + 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x54, 0x43, 0x50, 0x12, 0x10, 0x0a, 0x03, 0x55, 0x44, + 0x50, 0x18, 0x20, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x44, 0x50, 0x12, 0x35, 0x0a, 0x08, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x76, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, 0x65, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x4e, 0x6f, 0x64, + 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x44, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x11, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x53, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x48, 0x32, 0x50, + 0x49, 0x4e, 0x47, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x48, 0x32, 0x50, 0x49, 0x4e, + 0x47, 0x12, 0x22, 0x0a, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x65, 0x54, 0x4c, + 0x53, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x48, 0x32, 0x50, 0x69, 0x6e, 0x67, 0x55, + 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x47, 0x52, 0x50, 0x43, 0x18, 0x0e, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x47, 0x52, 0x50, 0x43, 0x12, 0x1e, 0x0a, 0x0a, 0x47, 0x52, 0x50, + 0x43, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x47, + 0x52, 0x50, 0x43, 0x55, 0x73, 0x65, 0x54, 0x4c, 0x53, 0x12, 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x24, 0x0a, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, + 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x54, 0x4c, 0x53, 0x53, 0x6b, 0x69, 0x70, 0x56, + 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x33, 0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, + 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x2b, 0x0a, 0x03, 0x54, 0x54, + 0x4c, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x54, 0x4c, 0x12, 0x32, 0x0a, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, + 0x15, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x42, 0x65, + 0x66, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x15, 0x46, + 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, + 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x15, 0x46, 0x61, 0x69, 0x6c, + 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, + 0x67, 0x12, 0x36, 0x0a, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, + 0x6f, 0x72, 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x18, 0x16, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x16, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, + 0x65, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x48, 0x54, 0x54, 0x50, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, + 0x6f, 0x78, 0x79, 0x48, 0x54, 0x54, 0x50, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, + 0x47, 0x52, 0x50, 0x43, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x47, 0x52, 0x50, 0x43, 0x12, 0x61, 0x0a, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, + 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x1e, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, + 0x73, 0x74, 0x65, 0x72, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x4f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x19, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x0d, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4d, 0x61, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x69, + 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x44, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, + 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x88, 0x01, 0x0a, 0x0b, 0x63, 0x6f, - 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58, - 0xaa, 0x02, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x07, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0xe2, 0x02, 0x13, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5c, 0x47, - 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x8e, 0x02, 0x0a, 0x25, 0x63, 0x6f, + 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x42, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x53, 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, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 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, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1023,32 +1045,32 @@ func file_proto_pbservice_healthcheck_proto_rawDescGZIP() []byte { var file_proto_pbservice_healthcheck_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_proto_pbservice_healthcheck_proto_goTypes = []interface{}{ - (*HealthCheck)(nil), // 0: service.HealthCheck - (*HeaderValue)(nil), // 1: service.HeaderValue - (*HealthCheckDefinition)(nil), // 2: service.HealthCheckDefinition - (*CheckType)(nil), // 3: service.CheckType - nil, // 4: service.HealthCheckDefinition.HeaderEntry - nil, // 5: service.CheckType.HeaderEntry - (*pbcommon.RaftIndex)(nil), // 6: common.RaftIndex - (*pbcommon.EnterpriseMeta)(nil), // 7: common.EnterpriseMeta + (*HealthCheck)(nil), // 0: hashicorp.consul.internal.service.HealthCheck + (*HeaderValue)(nil), // 1: hashicorp.consul.internal.service.HeaderValue + (*HealthCheckDefinition)(nil), // 2: hashicorp.consul.internal.service.HealthCheckDefinition + (*CheckType)(nil), // 3: hashicorp.consul.internal.service.CheckType + nil, // 4: hashicorp.consul.internal.service.HealthCheckDefinition.HeaderEntry + nil, // 5: hashicorp.consul.internal.service.CheckType.HeaderEntry + (*pbcommon.RaftIndex)(nil), // 6: hashicorp.consul.internal.common.RaftIndex + (*pbcommon.EnterpriseMeta)(nil), // 7: hashicorp.consul.internal.common.EnterpriseMeta (*durationpb.Duration)(nil), // 8: google.protobuf.Duration } var file_proto_pbservice_healthcheck_proto_depIdxs = []int32{ - 2, // 0: service.HealthCheck.Definition:type_name -> service.HealthCheckDefinition - 6, // 1: service.HealthCheck.RaftIndex:type_name -> common.RaftIndex - 7, // 2: service.HealthCheck.EnterpriseMeta:type_name -> common.EnterpriseMeta - 4, // 3: service.HealthCheckDefinition.Header:type_name -> service.HealthCheckDefinition.HeaderEntry - 8, // 4: service.HealthCheckDefinition.Interval:type_name -> google.protobuf.Duration - 8, // 5: service.HealthCheckDefinition.Timeout:type_name -> google.protobuf.Duration - 8, // 6: service.HealthCheckDefinition.DeregisterCriticalServiceAfter:type_name -> google.protobuf.Duration - 8, // 7: service.HealthCheckDefinition.TTL:type_name -> google.protobuf.Duration - 5, // 8: service.CheckType.Header:type_name -> service.CheckType.HeaderEntry - 8, // 9: service.CheckType.Interval:type_name -> google.protobuf.Duration - 8, // 10: service.CheckType.Timeout:type_name -> google.protobuf.Duration - 8, // 11: service.CheckType.TTL:type_name -> google.protobuf.Duration - 8, // 12: service.CheckType.DeregisterCriticalServiceAfter:type_name -> google.protobuf.Duration - 1, // 13: service.HealthCheckDefinition.HeaderEntry.value:type_name -> service.HeaderValue - 1, // 14: service.CheckType.HeaderEntry.value:type_name -> service.HeaderValue + 2, // 0: hashicorp.consul.internal.service.HealthCheck.Definition:type_name -> hashicorp.consul.internal.service.HealthCheckDefinition + 6, // 1: hashicorp.consul.internal.service.HealthCheck.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex + 7, // 2: hashicorp.consul.internal.service.HealthCheck.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 4, // 3: hashicorp.consul.internal.service.HealthCheckDefinition.Header:type_name -> hashicorp.consul.internal.service.HealthCheckDefinition.HeaderEntry + 8, // 4: hashicorp.consul.internal.service.HealthCheckDefinition.Interval:type_name -> google.protobuf.Duration + 8, // 5: hashicorp.consul.internal.service.HealthCheckDefinition.Timeout:type_name -> google.protobuf.Duration + 8, // 6: hashicorp.consul.internal.service.HealthCheckDefinition.DeregisterCriticalServiceAfter:type_name -> google.protobuf.Duration + 8, // 7: hashicorp.consul.internal.service.HealthCheckDefinition.TTL:type_name -> google.protobuf.Duration + 5, // 8: hashicorp.consul.internal.service.CheckType.Header:type_name -> hashicorp.consul.internal.service.CheckType.HeaderEntry + 8, // 9: hashicorp.consul.internal.service.CheckType.Interval:type_name -> google.protobuf.Duration + 8, // 10: hashicorp.consul.internal.service.CheckType.Timeout:type_name -> google.protobuf.Duration + 8, // 11: hashicorp.consul.internal.service.CheckType.TTL:type_name -> google.protobuf.Duration + 8, // 12: hashicorp.consul.internal.service.CheckType.DeregisterCriticalServiceAfter:type_name -> google.protobuf.Duration + 1, // 13: hashicorp.consul.internal.service.HealthCheckDefinition.HeaderEntry.value:type_name -> hashicorp.consul.internal.service.HeaderValue + 1, // 14: hashicorp.consul.internal.service.CheckType.HeaderEntry.value:type_name -> hashicorp.consul.internal.service.HeaderValue 15, // [15:15] is the sub-list for method output_type 15, // [15:15] is the sub-list for method input_type 15, // [15:15] is the sub-list for extension type_name diff --git a/proto/pbservice/healthcheck.proto b/proto/pbservice/healthcheck.proto index 6e00548a42..1149a0ac99 100644 --- a/proto/pbservice/healthcheck.proto +++ b/proto/pbservice/healthcheck.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package service; +package hashicorp.consul.internal.service; import "google/protobuf/duration.proto"; import "proto/pbcommon/common.proto"; diff --git a/proto/pbservice/node.pb.go b/proto/pbservice/node.pb.go index fee4534f8a..6d0ebfacfb 100644 --- a/proto/pbservice/node.pb.go +++ b/proto/pbservice/node.pb.go @@ -486,48 +486,61 @@ var File_proto_pbservice_node_proto protoreflect.FileDescriptor var file_proto_pbservice_node_proto_rawDesc = []byte{ 0x0a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x61, 0x0a, 0x18, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, - 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, - 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x2f, 0x0a, 0x05, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x65, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, + 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, + 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x68, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x1d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x7b, + 0x0a, 0x18, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x64, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, + 0x12, 0x49, 0x0a, 0x05, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 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, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0xe1, 0x01, 0x0a, 0x10, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, - 0x52, 0x05, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x93, 0x01, 0x0a, 0x10, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x21, 0x0a, 0x04, - 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, - 0x2e, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, - 0x2c, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x22, 0xc7, 0x03, - 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, - 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, - 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1e, - 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x4c, - 0x0a, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x54, 0x61, 0x67, - 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x04, - 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, - 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x2f, 0x0a, 0x09, 0x52, 0x61, 0x66, - 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, + 0x12, 0x3b, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, + 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, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x48, 0x0a, + 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, + 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, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x46, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x48, 0x65, 0x61, 0x6c, + 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x22, + 0x95, 0x04, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, + 0x12, 0x66, 0x0a, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4e, 0x6f, + 0x64, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x2e, + 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, + 0x49, 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2b, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x1a, 0x42, 0x0a, 0x14, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, @@ -537,7 +550,7 @@ var file_proto_pbservice_node_proto_rawDesc = []byte{ 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, 0xd9, 0x06, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa9, 0x08, 0x0a, 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x18, 0x0a, 0x07, 0x53, @@ -545,61 +558,83 @@ var file_proto_pbservice_node_proto_rawDesc = []byte{ 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x12, 0x53, 0x0a, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, - 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, - 0x50, 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, - 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x11, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, - 0x12, 0x2a, 0x0a, 0x07, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x57, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x73, 0x52, 0x07, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x11, - 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, - 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, - 0x61, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x31, 0x0a, 0x05, 0x50, 0x72, - 0x6f, 0x78, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x31, 0x0a, - 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x12, 0x3e, 0x0a, 0x1a, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x65, 0x72, 0x65, 0x64, 0x41, 0x73, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x67, + 0x65, 0x73, 0x73, 0x12, 0x6d, 0x0a, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, 0x61, 0x67, + 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x52, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x65, 0x73, 0x12, 0x4c, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, + 0x32, 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, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, + 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, + 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, + 0x74, 0x68, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x50, 0x61, 0x74, 0x68, 0x12, 0x44, 0x0a, 0x07, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, + 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, + 0x73, 0x52, 0x07, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x45, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x67, + 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x4b, 0x0a, 0x05, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x18, 0x0b, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, + 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x4b, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x12, 0x3e, 0x0a, 0x1a, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x41, 0x73, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, - 0x12, 0x3e, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x09, - 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x11, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, - 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x1a, 0x5b, 0x0a, - 0x14, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x41, 0x73, 0x53, 0x69, 0x64, 0x65, 0x63, + 0x61, 0x72, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, + 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x49, 0x0a, 0x09, 0x52, 0x61, 0x66, 0x74, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x52, + 0x61, 0x66, 0x74, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x09, 0x52, 0x61, 0x66, 0x74, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x1a, 0x75, 0x0a, 0x14, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x47, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 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, 0x42, 0x81, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x42, 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xa2, 0x02, 0x03, - 0x53, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, 0x02, 0x07, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xe2, 0x02, 0x13, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x02, 0x38, 0x01, 0x42, 0x87, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x09, 0x4e, + 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x53, 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, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 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, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -616,38 +651,38 @@ func file_proto_pbservice_node_proto_rawDescGZIP() []byte { var file_proto_pbservice_node_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_proto_pbservice_node_proto_goTypes = []interface{}{ - (*IndexedCheckServiceNodes)(nil), // 0: service.IndexedCheckServiceNodes - (*CheckServiceNode)(nil), // 1: service.CheckServiceNode - (*Node)(nil), // 2: service.Node - (*NodeService)(nil), // 3: service.NodeService - nil, // 4: service.Node.TaggedAddressesEntry - nil, // 5: service.Node.MetaEntry - nil, // 6: service.NodeService.TaggedAddressesEntry - nil, // 7: service.NodeService.MetaEntry - (*HealthCheck)(nil), // 8: service.HealthCheck - (*pbcommon.RaftIndex)(nil), // 9: common.RaftIndex - (*Weights)(nil), // 10: service.Weights - (*ConnectProxyConfig)(nil), // 11: service.ConnectProxyConfig - (*ServiceConnect)(nil), // 12: service.ServiceConnect - (*pbcommon.EnterpriseMeta)(nil), // 13: common.EnterpriseMeta - (*ServiceAddress)(nil), // 14: service.ServiceAddress + (*IndexedCheckServiceNodes)(nil), // 0: hashicorp.consul.internal.service.IndexedCheckServiceNodes + (*CheckServiceNode)(nil), // 1: hashicorp.consul.internal.service.CheckServiceNode + (*Node)(nil), // 2: hashicorp.consul.internal.service.Node + (*NodeService)(nil), // 3: hashicorp.consul.internal.service.NodeService + nil, // 4: hashicorp.consul.internal.service.Node.TaggedAddressesEntry + nil, // 5: hashicorp.consul.internal.service.Node.MetaEntry + nil, // 6: hashicorp.consul.internal.service.NodeService.TaggedAddressesEntry + nil, // 7: hashicorp.consul.internal.service.NodeService.MetaEntry + (*HealthCheck)(nil), // 8: hashicorp.consul.internal.service.HealthCheck + (*pbcommon.RaftIndex)(nil), // 9: hashicorp.consul.internal.common.RaftIndex + (*Weights)(nil), // 10: hashicorp.consul.internal.service.Weights + (*ConnectProxyConfig)(nil), // 11: hashicorp.consul.internal.service.ConnectProxyConfig + (*ServiceConnect)(nil), // 12: hashicorp.consul.internal.service.ServiceConnect + (*pbcommon.EnterpriseMeta)(nil), // 13: hashicorp.consul.internal.common.EnterpriseMeta + (*ServiceAddress)(nil), // 14: hashicorp.consul.internal.service.ServiceAddress } var file_proto_pbservice_node_proto_depIdxs = []int32{ - 1, // 0: service.IndexedCheckServiceNodes.Nodes:type_name -> service.CheckServiceNode - 2, // 1: service.CheckServiceNode.Node:type_name -> service.Node - 3, // 2: service.CheckServiceNode.Service:type_name -> service.NodeService - 8, // 3: service.CheckServiceNode.Checks:type_name -> service.HealthCheck - 4, // 4: service.Node.TaggedAddresses:type_name -> service.Node.TaggedAddressesEntry - 5, // 5: service.Node.Meta:type_name -> service.Node.MetaEntry - 9, // 6: service.Node.RaftIndex:type_name -> common.RaftIndex - 6, // 7: service.NodeService.TaggedAddresses:type_name -> service.NodeService.TaggedAddressesEntry - 7, // 8: service.NodeService.Meta:type_name -> service.NodeService.MetaEntry - 10, // 9: service.NodeService.Weights:type_name -> service.Weights - 11, // 10: service.NodeService.Proxy:type_name -> service.ConnectProxyConfig - 12, // 11: service.NodeService.Connect:type_name -> service.ServiceConnect - 13, // 12: service.NodeService.EnterpriseMeta:type_name -> common.EnterpriseMeta - 9, // 13: service.NodeService.RaftIndex:type_name -> common.RaftIndex - 14, // 14: service.NodeService.TaggedAddressesEntry.value:type_name -> service.ServiceAddress + 1, // 0: hashicorp.consul.internal.service.IndexedCheckServiceNodes.Nodes:type_name -> hashicorp.consul.internal.service.CheckServiceNode + 2, // 1: hashicorp.consul.internal.service.CheckServiceNode.Node:type_name -> hashicorp.consul.internal.service.Node + 3, // 2: hashicorp.consul.internal.service.CheckServiceNode.Service:type_name -> hashicorp.consul.internal.service.NodeService + 8, // 3: hashicorp.consul.internal.service.CheckServiceNode.Checks:type_name -> hashicorp.consul.internal.service.HealthCheck + 4, // 4: hashicorp.consul.internal.service.Node.TaggedAddresses:type_name -> hashicorp.consul.internal.service.Node.TaggedAddressesEntry + 5, // 5: hashicorp.consul.internal.service.Node.Meta:type_name -> hashicorp.consul.internal.service.Node.MetaEntry + 9, // 6: hashicorp.consul.internal.service.Node.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex + 6, // 7: hashicorp.consul.internal.service.NodeService.TaggedAddresses:type_name -> hashicorp.consul.internal.service.NodeService.TaggedAddressesEntry + 7, // 8: hashicorp.consul.internal.service.NodeService.Meta:type_name -> hashicorp.consul.internal.service.NodeService.MetaEntry + 10, // 9: hashicorp.consul.internal.service.NodeService.Weights:type_name -> hashicorp.consul.internal.service.Weights + 11, // 10: hashicorp.consul.internal.service.NodeService.Proxy:type_name -> hashicorp.consul.internal.service.ConnectProxyConfig + 12, // 11: hashicorp.consul.internal.service.NodeService.Connect:type_name -> hashicorp.consul.internal.service.ServiceConnect + 13, // 12: hashicorp.consul.internal.service.NodeService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 9, // 13: hashicorp.consul.internal.service.NodeService.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex + 14, // 14: hashicorp.consul.internal.service.NodeService.TaggedAddressesEntry.value:type_name -> hashicorp.consul.internal.service.ServiceAddress 15, // [15:15] is the sub-list for method output_type 15, // [15:15] is the sub-list for method input_type 15, // [15:15] is the sub-list for extension type_name diff --git a/proto/pbservice/node.proto b/proto/pbservice/node.proto index b26bac51fc..7431b836ce 100644 --- a/proto/pbservice/node.proto +++ b/proto/pbservice/node.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package service; +package hashicorp.consul.internal.service; import "proto/pbcommon/common.proto"; import "proto/pbservice/healthcheck.proto"; diff --git a/proto/pbservice/service.pb.go b/proto/pbservice/service.pb.go index 89ff546dc5..6ad9ea5394 100644 --- a/proto/pbservice/service.pb.go +++ b/proto/pbservice/service.pb.go @@ -1114,96 +1114,109 @@ var File_proto_pbservice_service_proto protoreflect.FileDescriptor var file_proto_pbservice_service_proto_rawDesc = []byte{ 0x0a, 0x1d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2f, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc6, 0x04, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, - 0x16, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x44, + 0x21, 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, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x68, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0xae, 0x05, 0x0a, 0x12, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x16, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x32, 0x0a, 0x14, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x32, 0x0a, 0x14, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x14, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x44, 0x12, 0x30, 0x0a, 0x13, 0x4c, 0x6f, 0x63, - 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, - 0x52, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2f, 0x0a, 0x09, 0x55, 0x70, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x09, - 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x3c, 0x0a, 0x0b, 0x4d, 0x65, 0x73, - 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, - 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2d, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x73, - 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, - 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x4b, 0x0a, 0x10, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x36, 0x0a, 0x16, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x65, 0x49, 0x44, 0x12, 0x30, 0x0a, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2a, 0x0a, 0x10, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x10, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x6f, 0x72, + 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x49, 0x0a, 0x09, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x52, 0x09, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x56, 0x0a, + 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 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, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x47, 0x0a, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, + 0x64, 0x65, 0x12, 0x65, 0x0a, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, + 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x36, 0x0a, 0x16, 0x4c, 0x6f, 0x63, + 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, + 0x61, 0x74, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, - 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x22, - 0xe7, 0x04, 0x0a, 0x08, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0f, - 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x32, 0x0a, 0x14, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x32, 0x0a, 0x14, 0x44, 0x65, - 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x28, - 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x65, - 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, - 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x24, - 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, - 0x50, 0x6f, 0x72, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x12, 0x30, 0x0a, 0x13, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x6c, 0x79, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x13, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x65, 0x64, 0x12, 0x30, 0x0a, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, - 0x6e, 0x64, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x30, 0x0a, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x42, 0x69, 0x6e, 0x64, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x53, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xab, 0x01, 0x0a, 0x0e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x4e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x4e, 0x61, - 0x74, 0x69, 0x76, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, - 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, - 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, - 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x65, 0x72, + 0x68, 0x22, 0x81, 0x05, 0x0a, 0x08, 0x55, 0x70, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x28, + 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x32, 0x0a, 0x14, 0x44, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x32, 0x0a, 0x14, + 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x74, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x44, 0x65, 0x73, 0x74, + 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x28, 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x65, 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x65, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x0f, 0x44, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0f, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x0a, 0x10, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, + 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x24, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x50, 0x6f, 0x72, + 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, + 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, + 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x56, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x0b, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, + 0x30, 0x0a, 0x13, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x43, 0x65, + 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x6c, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, + 0x64, 0x12, 0x30, 0x0a, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x30, 0x0a, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, + 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x13, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x42, 0x69, 0x6e, 0x64, 0x53, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0xdf, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x61, 0x74, 0x69, + 0x76, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x4e, 0x61, 0x74, 0x69, 0x76, 0x65, + 0x12, 0x5c, 0x0a, 0x0e, 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0e, + 0x53, 0x69, 0x64, 0x65, 0x63, 0x61, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, + 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x5e, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, @@ -1212,103 +1225,127 @@ var file_proto_pbservice_service_proto_rawDesc = []byte{ 0x1a, 0x0a, 0x08, 0x53, 0x70, 0x69, 0x66, 0x66, 0x65, 0x49, 0x44, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x53, 0x70, 0x69, 0x66, 0x66, 0x65, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x51, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x6f, 0x73, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x6b, 0x0a, 0x0c, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, - 0x29, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, - 0x61, 0x74, 0x68, 0x52, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x45, - 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x4c, 0x69, 0x73, - 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, - 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, - 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, - 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x12, 0x28, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, - 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x50, 0x61, - 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0x27, 0x0a, - 0x11, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x22, 0x74, 0x0a, 0x16, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x32, 0x0a, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, - 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, - 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, - 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, - 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x44, 0x69, - 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x22, 0xc4, 0x06, 0x0a, - 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, - 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x18, - 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x59, 0x0a, 0x0f, 0x54, 0x61, 0x67, 0x67, - 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x61, - 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x24, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, - 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, - 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, - 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, - 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, - 0x68, 0x12, 0x28, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x12, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x2a, 0x0a, 0x06, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, - 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x2a, 0x0a, 0x07, 0x57, 0x65, 0x69, 0x67, 0x68, - 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x2e, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x52, 0x07, 0x57, 0x65, 0x69, 0x67, - 0x68, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2c, 0x0a, 0x11, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x0c, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x4f, - 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x31, 0x0a, 0x05, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x05, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x3e, 0x0a, 0x0e, 0x45, 0x6e, - 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x11, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, + 0x43, 0x0a, 0x05, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, + 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, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x05, 0x50, + 0x61, 0x74, 0x68, 0x73, 0x22, 0xb0, 0x01, 0x0a, 0x0a, 0x45, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, + 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x65, + 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x61, 0x74, 0x68, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0d, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x50, 0x6f, 0x72, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x28, 0x0a, + 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x50, 0x61, 0x72, 0x73, 0x65, 0x64, 0x46, 0x72, + 0x6f, 0x6d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0x27, 0x0a, 0x11, 0x4d, 0x65, 0x73, 0x68, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, + 0x4d, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4d, 0x6f, 0x64, 0x65, + 0x22, 0x74, 0x0a, 0x16, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x32, 0x0a, 0x14, 0x4f, 0x75, + 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, + 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, + 0x6e, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x26, + 0x0a, 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x44, 0x69, 0x61, 0x6c, 0x65, 0x64, 0x44, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x22, 0xae, 0x08, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, + 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, + 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x61, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x04, 0x54, 0x61, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x73, 0x0a, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x52, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x44, 0x65, 0x66, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x65, 0x74, 0x61, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x50, + 0x6f, 0x72, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, + 0x1e, 0x0a, 0x0a, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x12, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, + 0x42, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, + 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, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x12, 0x44, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x09, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x2c, 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, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x79, 0x70, + 0x65, 0x52, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x12, 0x44, 0x0a, 0x07, 0x57, 0x65, 0x69, + 0x67, 0x68, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x57, + 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x52, 0x07, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, + 0x14, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x2c, 0x0a, 0x11, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, + 0x61, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x11, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x4f, 0x76, 0x65, 0x72, 0x72, + 0x69, 0x64, 0x65, 0x12, 0x4b, 0x0a, 0x05, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x0e, 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, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x50, 0x72, + 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x50, 0x72, 0x6f, 0x78, 0x79, + 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, - 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x31, 0x0a, 0x07, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x52, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x1a, 0x5b, 0x0a, - 0x14, 0x54, 0x61, 0x67, 0x67, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 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, 0x3e, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, - 0x6f, 0x72, 0x74, 0x22, 0x3d, 0x0a, 0x07, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x18, - 0x0a, 0x07, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x07, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x57, 0x61, 0x72, 0x6e, - 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x57, 0x61, 0x72, 0x6e, 0x69, - 0x6e, 0x67, 0x42, 0x84, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xa2, - 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xca, - 0x02, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xe2, 0x02, 0x13, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x4b, 0x0a, 0x07, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 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, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x07, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x1a, 0x75, 0x0a, 0x14, 0x54, 0x61, 0x67, 0x67, 0x65, + 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x47, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x31, 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, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 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, 0x3e, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x3d, 0x0a, 0x07, 0x57, 0x65, 0x69, 0x67, 0x68, + 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x07, 0x50, 0x61, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x18, 0x0a, 0x07, + 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x57, + 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x42, 0x8a, 0x02, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, + 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x42, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xa2, 0x02, 0x04, + 0x48, 0x43, 0x49, 0x53, 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, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 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, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 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, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1325,43 +1362,43 @@ func file_proto_pbservice_service_proto_rawDescGZIP() []byte { var file_proto_pbservice_service_proto_msgTypes = make([]protoimpl.MessageInfo, 13) var file_proto_pbservice_service_proto_goTypes = []interface{}{ - (*ConnectProxyConfig)(nil), // 0: service.ConnectProxyConfig - (*Upstream)(nil), // 1: service.Upstream - (*ServiceConnect)(nil), // 2: service.ServiceConnect - (*PeeringServiceMeta)(nil), // 3: service.PeeringServiceMeta - (*ExposeConfig)(nil), // 4: service.ExposeConfig - (*ExposePath)(nil), // 5: service.ExposePath - (*MeshGatewayConfig)(nil), // 6: service.MeshGatewayConfig - (*TransparentProxyConfig)(nil), // 7: service.TransparentProxyConfig - (*ServiceDefinition)(nil), // 8: service.ServiceDefinition - (*ServiceAddress)(nil), // 9: service.ServiceAddress - (*Weights)(nil), // 10: service.Weights - nil, // 11: service.ServiceDefinition.TaggedAddressesEntry - nil, // 12: service.ServiceDefinition.MetaEntry + (*ConnectProxyConfig)(nil), // 0: hashicorp.consul.internal.service.ConnectProxyConfig + (*Upstream)(nil), // 1: hashicorp.consul.internal.service.Upstream + (*ServiceConnect)(nil), // 2: hashicorp.consul.internal.service.ServiceConnect + (*PeeringServiceMeta)(nil), // 3: hashicorp.consul.internal.service.PeeringServiceMeta + (*ExposeConfig)(nil), // 4: hashicorp.consul.internal.service.ExposeConfig + (*ExposePath)(nil), // 5: hashicorp.consul.internal.service.ExposePath + (*MeshGatewayConfig)(nil), // 6: hashicorp.consul.internal.service.MeshGatewayConfig + (*TransparentProxyConfig)(nil), // 7: hashicorp.consul.internal.service.TransparentProxyConfig + (*ServiceDefinition)(nil), // 8: hashicorp.consul.internal.service.ServiceDefinition + (*ServiceAddress)(nil), // 9: hashicorp.consul.internal.service.ServiceAddress + (*Weights)(nil), // 10: hashicorp.consul.internal.service.Weights + nil, // 11: hashicorp.consul.internal.service.ServiceDefinition.TaggedAddressesEntry + nil, // 12: hashicorp.consul.internal.service.ServiceDefinition.MetaEntry (*structpb.Struct)(nil), // 13: google.protobuf.Struct - (*CheckType)(nil), // 14: service.CheckType - (*pbcommon.EnterpriseMeta)(nil), // 15: common.EnterpriseMeta + (*CheckType)(nil), // 14: hashicorp.consul.internal.service.CheckType + (*pbcommon.EnterpriseMeta)(nil), // 15: hashicorp.consul.internal.common.EnterpriseMeta } var file_proto_pbservice_service_proto_depIdxs = []int32{ - 13, // 0: service.ConnectProxyConfig.Config:type_name -> google.protobuf.Struct - 1, // 1: service.ConnectProxyConfig.Upstreams:type_name -> service.Upstream - 6, // 2: service.ConnectProxyConfig.MeshGateway:type_name -> service.MeshGatewayConfig - 4, // 3: service.ConnectProxyConfig.Expose:type_name -> service.ExposeConfig - 7, // 4: service.ConnectProxyConfig.TransparentProxy:type_name -> service.TransparentProxyConfig - 13, // 5: service.Upstream.Config:type_name -> google.protobuf.Struct - 6, // 6: service.Upstream.MeshGateway:type_name -> service.MeshGatewayConfig - 8, // 7: service.ServiceConnect.SidecarService:type_name -> service.ServiceDefinition - 3, // 8: service.ServiceConnect.PeerMeta:type_name -> service.PeeringServiceMeta - 5, // 9: service.ExposeConfig.Paths:type_name -> service.ExposePath - 11, // 10: service.ServiceDefinition.TaggedAddresses:type_name -> service.ServiceDefinition.TaggedAddressesEntry - 12, // 11: service.ServiceDefinition.Meta:type_name -> service.ServiceDefinition.MetaEntry - 14, // 12: service.ServiceDefinition.Check:type_name -> service.CheckType - 14, // 13: service.ServiceDefinition.Checks:type_name -> service.CheckType - 10, // 14: service.ServiceDefinition.Weights:type_name -> service.Weights - 0, // 15: service.ServiceDefinition.Proxy:type_name -> service.ConnectProxyConfig - 15, // 16: service.ServiceDefinition.EnterpriseMeta:type_name -> common.EnterpriseMeta - 2, // 17: service.ServiceDefinition.Connect:type_name -> service.ServiceConnect - 9, // 18: service.ServiceDefinition.TaggedAddressesEntry.value:type_name -> service.ServiceAddress + 13, // 0: hashicorp.consul.internal.service.ConnectProxyConfig.Config:type_name -> google.protobuf.Struct + 1, // 1: hashicorp.consul.internal.service.ConnectProxyConfig.Upstreams:type_name -> hashicorp.consul.internal.service.Upstream + 6, // 2: hashicorp.consul.internal.service.ConnectProxyConfig.MeshGateway:type_name -> hashicorp.consul.internal.service.MeshGatewayConfig + 4, // 3: hashicorp.consul.internal.service.ConnectProxyConfig.Expose:type_name -> hashicorp.consul.internal.service.ExposeConfig + 7, // 4: hashicorp.consul.internal.service.ConnectProxyConfig.TransparentProxy:type_name -> hashicorp.consul.internal.service.TransparentProxyConfig + 13, // 5: hashicorp.consul.internal.service.Upstream.Config:type_name -> google.protobuf.Struct + 6, // 6: hashicorp.consul.internal.service.Upstream.MeshGateway:type_name -> hashicorp.consul.internal.service.MeshGatewayConfig + 8, // 7: hashicorp.consul.internal.service.ServiceConnect.SidecarService:type_name -> hashicorp.consul.internal.service.ServiceDefinition + 3, // 8: hashicorp.consul.internal.service.ServiceConnect.PeerMeta:type_name -> hashicorp.consul.internal.service.PeeringServiceMeta + 5, // 9: hashicorp.consul.internal.service.ExposeConfig.Paths:type_name -> hashicorp.consul.internal.service.ExposePath + 11, // 10: hashicorp.consul.internal.service.ServiceDefinition.TaggedAddresses:type_name -> hashicorp.consul.internal.service.ServiceDefinition.TaggedAddressesEntry + 12, // 11: hashicorp.consul.internal.service.ServiceDefinition.Meta:type_name -> hashicorp.consul.internal.service.ServiceDefinition.MetaEntry + 14, // 12: hashicorp.consul.internal.service.ServiceDefinition.Check:type_name -> hashicorp.consul.internal.service.CheckType + 14, // 13: hashicorp.consul.internal.service.ServiceDefinition.Checks:type_name -> hashicorp.consul.internal.service.CheckType + 10, // 14: hashicorp.consul.internal.service.ServiceDefinition.Weights:type_name -> hashicorp.consul.internal.service.Weights + 0, // 15: hashicorp.consul.internal.service.ServiceDefinition.Proxy:type_name -> hashicorp.consul.internal.service.ConnectProxyConfig + 15, // 16: hashicorp.consul.internal.service.ServiceDefinition.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 2, // 17: hashicorp.consul.internal.service.ServiceDefinition.Connect:type_name -> hashicorp.consul.internal.service.ServiceConnect + 9, // 18: hashicorp.consul.internal.service.ServiceDefinition.TaggedAddressesEntry.value:type_name -> hashicorp.consul.internal.service.ServiceAddress 19, // [19:19] is the sub-list for method output_type 19, // [19:19] is the sub-list for method input_type 19, // [19:19] is the sub-list for extension type_name diff --git a/proto/pbservice/service.proto b/proto/pbservice/service.proto index 9c7956a0d5..690a3b82a6 100644 --- a/proto/pbservice/service.proto +++ b/proto/pbservice/service.proto @@ -1,6 +1,6 @@ syntax = "proto3"; -package service; +package hashicorp.consul.internal.service; import "google/protobuf/struct.proto"; import "proto/pbcommon/common.proto"; diff --git a/proto/pbstatus/status.pb.go b/proto/pbstatus/status.pb.go index f97dbc7735..c69c57cbf2 100644 --- a/proto/pbstatus/status.pb.go +++ b/proto/pbstatus/status.pb.go @@ -115,24 +115,34 @@ var File_proto_pbstatus_status_proto protoreflect.FileDescriptor var file_proto_pbstatus_status_proto_rawDesc = []byte{ 0x0a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x22, 0x66, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, - 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, - 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x42, 0x7d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2a, 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, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0xca, 0x02, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0xe2, 0x02, 0x12, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, - 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x20, 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, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, + 0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x66, 0x0a, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x73, 0x42, 0x83, 0x02, 0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x0b, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2a, 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, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x53, 0xaa, 0x02, 0x20, + 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, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0xca, 0x02, 0x20, 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, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0xe2, 0x02, 0x2c, 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, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0xea, 0x02, 0x23, 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, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -149,11 +159,11 @@ func file_proto_pbstatus_status_proto_rawDescGZIP() []byte { var file_proto_pbstatus_status_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_proto_pbstatus_status_proto_goTypes = []interface{}{ - (*Status)(nil), // 0: status.Status + (*Status)(nil), // 0: hashicorp.consul.internal.status.Status (*anypb.Any)(nil), // 1: google.protobuf.Any } var file_proto_pbstatus_status_proto_depIdxs = []int32{ - 1, // 0: status.Status.details:type_name -> google.protobuf.Any + 1, // 0: hashicorp.consul.internal.status.Status.details:type_name -> google.protobuf.Any 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name diff --git a/proto/pbstatus/status.proto b/proto/pbstatus/status.proto index e483b19506..70fb3f58af 100644 --- a/proto/pbstatus/status.proto +++ b/proto/pbstatus/status.proto @@ -14,7 +14,7 @@ syntax = "proto3"; -package status; +package hashicorp.consul.internal.status; import "google/protobuf/any.proto"; diff --git a/proto/pbsubscribe/subscribe.pb.go b/proto/pbsubscribe/subscribe.pb.go index e3e992ea40..deb43bad4c 100644 --- a/proto/pbsubscribe/subscribe.pb.go +++ b/proto/pbsubscribe/subscribe.pb.go @@ -7,6 +7,12 @@ // protoc (unknown) // source: proto/pbsubscribe/subscribe.proto +// TODO: ideally we would have prefixed this package as +// "hashicorp.consul.internal.subscribe" before releasing but now correcting this will +// require a grpc passthrough service shim since the package name is part of +// the rpc method dispatch and editing it naively would break backwards +// compatibility. + package pbsubscribe import ( @@ -755,11 +761,11 @@ var File_proto_pbsubscribe_subscribe_proto protoreflect.FileDescriptor var file_proto_pbsubscribe_subscribe_proto_rawDesc = []byte{ 0x0a, 0x21, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x1a, 0x1a, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, - 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x70, 0x72, 0x6f, + 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x1a, 0x26, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x78, 0x0a, 0x0c, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, @@ -814,53 +820,57 @@ var file_proto_pbsubscribe_subscribe_proto_rawDesc = []byte{ 0x36, 0x0a, 0x0a, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x74, 0x63, 0x68, 0x12, 0x28, 0x0a, 0x06, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, - 0x06, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x82, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x72, 0x76, + 0x06, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x9c, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x24, 0x0a, 0x02, 0x4f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4f, - 0x70, 0x52, 0x02, 0x4f, 0x70, 0x12, 0x45, 0x0a, 0x10, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, + 0x70, 0x52, 0x02, 0x4f, 0x70, 0x12, 0x5f, 0x0a, 0x10, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x10, 0x43, 0x68, 0x65, 0x63, - 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0xaa, 0x01, 0x0a, - 0x11, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x12, 0x35, 0x0a, 0x02, 0x4f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, - 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4f, 0x70, 0x52, 0x02, 0x4f, 0x70, 0x12, 0x3a, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, - 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x22, 0x0a, 0x08, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, - 0x70, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x10, 0x00, 0x12, 0x0a, 0x0a, - 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x10, 0x01, 0x2a, 0x91, 0x01, 0x0a, 0x05, 0x54, 0x6f, - 0x70, 0x69, 0x63, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, - 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, 0x02, 0x12, 0x0e, 0x0a, - 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x03, 0x12, 0x13, 0x0a, - 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x72, - 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x10, 0x05, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x06, 0x2a, 0x29, 0x0a, - 0x09, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4f, 0x70, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x65, 0x72, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x01, 0x32, 0x59, 0x0a, 0x17, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x12, 0x1b, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, - 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, - 0x00, 0x30, 0x01, 0x42, 0x92, 0x01, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0x42, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 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, 0x73, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa, 0x02, 0x09, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xca, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0xe2, 0x02, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, - 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 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, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x10, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x22, 0xc4, 0x01, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x35, 0x0a, 0x02, + 0x4f, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x62, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x52, + 0x02, 0x4f, 0x70, 0x12, 0x54, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 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, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x22, 0x0a, 0x08, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4f, 0x70, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x10, + 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x10, 0x01, 0x2a, 0x91, 0x01, + 0x0a, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, + 0x77, 0x6e, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x10, + 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, + 0x03, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x72, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x6e, 0x67, 0x72, 0x65, 0x73, + 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x05, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, + 0x06, 0x2a, 0x29, 0x0a, 0x09, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4f, 0x70, 0x12, 0x0c, + 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, + 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x01, 0x32, 0x59, 0x0a, 0x17, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x62, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x10, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x22, 0x00, 0x30, 0x01, 0x42, 0x92, 0x01, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x42, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x62, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 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, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58, + 0xaa, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xca, 0x02, 0x09, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xe2, 0x02, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x62, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -887,8 +897,8 @@ var file_proto_pbsubscribe_subscribe_proto_goTypes = []interface{}{ (*EventBatch)(nil), // 6: subscribe.EventBatch (*ServiceHealthUpdate)(nil), // 7: subscribe.ServiceHealthUpdate (*ConfigEntryUpdate)(nil), // 8: subscribe.ConfigEntryUpdate - (*pbservice.CheckServiceNode)(nil), // 9: service.CheckServiceNode - (*pbconfigentry.ConfigEntry)(nil), // 10: configentry.ConfigEntry + (*pbservice.CheckServiceNode)(nil), // 9: hashicorp.consul.internal.service.CheckServiceNode + (*pbconfigentry.ConfigEntry)(nil), // 10: hashicorp.consul.internal.configentry.ConfigEntry } var file_proto_pbsubscribe_subscribe_proto_depIdxs = []int32{ 0, // 0: subscribe.SubscribeRequest.Topic:type_name -> subscribe.Topic @@ -898,9 +908,9 @@ var file_proto_pbsubscribe_subscribe_proto_depIdxs = []int32{ 8, // 4: subscribe.Event.ConfigEntry:type_name -> subscribe.ConfigEntryUpdate 5, // 5: subscribe.EventBatch.Events:type_name -> subscribe.Event 1, // 6: subscribe.ServiceHealthUpdate.Op:type_name -> subscribe.CatalogOp - 9, // 7: subscribe.ServiceHealthUpdate.CheckServiceNode:type_name -> service.CheckServiceNode + 9, // 7: subscribe.ServiceHealthUpdate.CheckServiceNode:type_name -> hashicorp.consul.internal.service.CheckServiceNode 2, // 8: subscribe.ConfigEntryUpdate.Op:type_name -> subscribe.ConfigEntryUpdate.UpdateOp - 10, // 9: subscribe.ConfigEntryUpdate.ConfigEntry:type_name -> configentry.ConfigEntry + 10, // 9: subscribe.ConfigEntryUpdate.ConfigEntry:type_name -> hashicorp.consul.internal.configentry.ConfigEntry 4, // 10: subscribe.StateChangeSubscription.Subscribe:input_type -> subscribe.SubscribeRequest 5, // 11: subscribe.StateChangeSubscription.Subscribe:output_type -> subscribe.Event 11, // [11:12] is the sub-list for method output_type diff --git a/proto/pbsubscribe/subscribe.proto b/proto/pbsubscribe/subscribe.proto index f5bbcea9e6..4f1e092c46 100644 --- a/proto/pbsubscribe/subscribe.proto +++ b/proto/pbsubscribe/subscribe.proto @@ -3,10 +3,15 @@ Package event provides a service for subscribing to state change events. */ syntax = "proto3"; +// TODO: ideally we would have prefixed this package as +// "hashicorp.consul.internal.subscribe" before releasing but now correcting this will +// require a grpc passthrough service shim since the package name is part of +// the rpc method dispatch and editing it naively would break backwards +// compatibility. package subscribe; -import "proto/pbservice/node.proto"; import "proto/pbconfigentry/config_entry.proto"; +import "proto/pbservice/node.proto"; // StateChangeSubscription service allows consumers to subscribe to topics of // state change events. Events are streamed as they happen. @@ -180,7 +185,7 @@ enum CatalogOp { message ServiceHealthUpdate { CatalogOp Op = 1; - service.CheckServiceNode CheckServiceNode = 2; + hashicorp.consul.internal.service.CheckServiceNode CheckServiceNode = 2; } message ConfigEntryUpdate { @@ -190,5 +195,5 @@ message ConfigEntryUpdate { } UpdateOp Op = 1; - configentry.ConfigEntry ConfigEntry = 2; + hashicorp.consul.internal.configentry.ConfigEntry ConfigEntry = 2; } diff --git a/sdk/testutil/server.go b/sdk/testutil/server.go index 5f43bd9986..77fd90e824 100644 --- a/sdk/testutil/server.go +++ b/sdk/testutil/server.go @@ -51,6 +51,7 @@ type TestPortConfig struct { SerfLan int `json:"serf_lan,omitempty"` SerfWan int `json:"serf_wan,omitempty"` Server int `json:"server,omitempty"` + GRPC int `json:"grpc,omitempty"` ProxyMinPort int `json:"proxy_min_port,omitempty"` ProxyMaxPort int `json:"proxy_max_port,omitempty"` } @@ -150,7 +151,7 @@ func defaultServerConfig(t TestingTB) *TestServerConfig { panic(err) } - ports, err := freeport.Take(6) + ports, err := freeport.Take(7) if err != nil { t.Fatalf("failed to take ports: %v", err) } @@ -176,6 +177,7 @@ func defaultServerConfig(t TestingTB) *TestServerConfig { SerfLan: ports[3], SerfWan: ports[4], Server: ports[5], + GRPC: ports[6], }, ReadyTimeout: 10 * time.Second, StopTimeout: 10 * time.Second, @@ -226,6 +228,7 @@ type TestServer struct { HTTPSAddr string LANAddr string WANAddr string + GRPCAddr string HTTPClient *http.Client @@ -306,6 +309,7 @@ func NewTestServerConfigT(t TestingTB, cb ServerConfigCallback) (*TestServer, er HTTPSAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.HTTPS), LANAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.SerfLan), WANAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.SerfWan), + GRPCAddr: fmt.Sprintf("127.0.0.1:%d", cfg.Ports.GRPC), HTTPClient: client, diff --git a/test/integration/connect/envoy/run-tests.sh b/test/integration/connect/envoy/run-tests.sh index adea350d77..21705a3ae3 100755 --- a/test/integration/connect/envoy/run-tests.sh +++ b/test/integration/connect/envoy/run-tests.sh @@ -170,7 +170,8 @@ function start_consul { # an agent. # # When XDS_TARGET=client we'll start a Consul server with its gRPC port - # disabled, and a client agent with its gRPC port enabled. + # disabled (but only if REQUIRE_PEERS is not set), and a client agent with + # its gRPC port enabled. # # When XDS_TARGET=server (or anything else) we'll run a single Consul server # with its gRPC port enabled. @@ -196,6 +197,11 @@ function start_consul { docker_kill_rm consul-${DC}-server docker_kill_rm consul-${DC} + server_grpc_port="-1" + if is_set $REQUIRE_PEERS; then + server_grpc_port="8502" + fi + docker run -d --name envoy_consul-${DC}-server_1 \ --net=envoy-tests \ $WORKDIR_SNIPPET \ @@ -206,7 +212,7 @@ function start_consul { agent -dev -datacenter "${DC}" \ -config-dir "/workdir/${DC}/consul" \ -config-dir "/workdir/${DC}/consul-server" \ - -grpc-port -1 \ + -grpc-port $server_grpc_port \ -client "0.0.0.0" \ -bind "0.0.0.0" >/dev/null diff --git a/tools/private-grpc-proxy/main.go b/tools/internal-grpc-proxy/main.go similarity index 95% rename from tools/private-grpc-proxy/main.go rename to tools/internal-grpc-proxy/main.go index 32a7633f66..f134bfc50c 100644 --- a/tools/private-grpc-proxy/main.go +++ b/tools/internal-grpc-proxy/main.go @@ -24,7 +24,7 @@ func main() { } defer lis.Close() - fmt.Println("Proxying connections to Consul's private gRPC server") + fmt.Println("Proxying connections to Consul's internal gRPC server") fmt.Printf("Use this address: %s\n", lis.Addr()) for { diff --git a/ui/package.json b/ui/package.json index edfb47355c..1eb11e64fb 100644 --- a/ui/package.json +++ b/ui/package.json @@ -11,7 +11,7 @@ "scripts": { "doc:toc": "doctoc README.md", "compliance": "npm-run-all compliance:*", - "compliance:licenses": "license-checker --summary --onlyAllow 'Python-2.0;Apache*;Apache License, Version 2.0;Apache-2.0;Apache 2.0;Artistic-2.0;BSD;BSD-3-Clause;CC-BY-3.0;CC-BY-4.0;CC0-1.0;ISC;MIT;MPL-2.0;Public Domain;Unicode-TOU;Unlicense;WTFPL' --excludePackages 'consul-ui@2.2.0;consul-acls@0.1.0;consul-lock-sessions@0.1.0;consul-partitions@0.1.0;consul-nspaces@0.1.0;consul-hcp@0.1.0'" + "compliance:licenses": "license-checker --summary --onlyAllow 'Python-2.0;Apache*;Apache License, Version 2.0;Apache-2.0;Apache 2.0;Artistic-2.0;BSD;BSD-3-Clause;CC-BY-3.0;CC-BY-4.0;CC0-1.0;ISC;MIT;MPL-2.0;Public Domain;Unicode-TOU;Unlicense;WTFPL' --excludePackages 'consul-ui@2.2.0;consul-acls@0.1.0;consul-lock-sessions@0.1.0;consul-partitions@0.1.0;consul-nspaces@0.1.0;consul-hcp@0.1.0;consul-peerings@0.1.0'" }, "devDependencies": { diff --git a/ui/packages/consul-ui/app/components/consul/peer/address/list/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/address/list/index.hbs similarity index 100% rename from ui/packages/consul-ui/app/components/consul/peer/address/list/index.hbs rename to ui/packages/consul-peerings/app/components/consul/peer/address/list/index.hbs diff --git a/ui/packages/consul-peerings/app/components/consul/peer/components.scss b/ui/packages/consul-peerings/app/components/consul/peer/components.scss new file mode 100644 index 0000000000..d4fdbe0813 --- /dev/null +++ b/ui/packages/consul-peerings/app/components/consul/peer/components.scss @@ -0,0 +1,76 @@ +%pill-pending::before, +%pill-establishing::before, +%pill-active::before, +%pill-failing::before, +%pill-terminated::before, +%pill-deleting::before { + --icon-size: icon-000; + content: ''; +} +%pill-pending, +%pill-establishing, +%pill-active, +%pill-failing, +%pill-terminated, +%pill-deleting { + font-weight: var(--typo-weight-medium); + font-size: var(--typo-size-700); +} + +%pill-pending::before { + --icon-name: icon-running; + --icon-color: rgb(var(--tone-gray-800)); +} +%pill-pending { + background-color: rgb(var(--tone-strawberry-050)); + color: rgb(var(--tone-strawberry-500)); +} + +%pill-establishing::before { + --icon-name: icon-running; + --icon-color: rgb(var(--tone-gray-800)); +} +%pill-establishing { + background-color: rgb(var(--tone-blue-050)); + color: rgb(var(--tone-blue-500)); +} + +%pill-active::before { + --icon-name: icon-check; + --icon-color: rgb(var(--tone-green-800)); +} +%pill-active { + background-color: rgb(var(--tone-green-050)); + color: rgb(var(--tone-green-600)); +} + +%pill-failing::before { + --icon-name: icon-x; + --icon-color: rgb(var(--tone-red-500)); +} +%pill-failing { + background-color: rgb(var(--tone-red-050)); + color: rgb(var(--tone-red-500)); +} + +%pill-terminated::before { + --icon-name: icon-x-square; + --icon-color: rgb(var(--tone-gray-800)); +} +%pill-terminated { + background-color: rgb(var(--tone-gray-150)); + color: rgb(var(--tone-gray-800)); +} + + +%pill-deleting::before { + --icon-name: icon-loading; + --icon-color: rgb(var(--tone-green-800)); +} +%pill-deleting { + background-color: rgb(var(--tone-yellow-050)); + color: rgb(var(--tone-yellow-800)); +} + + + diff --git a/ui/packages/consul-peerings/app/components/consul/peer/index.scss b/ui/packages/consul-peerings/app/components/consul/peer/index.scss new file mode 100644 index 0000000000..9f82e6a21f --- /dev/null +++ b/ui/packages/consul-peerings/app/components/consul/peer/index.scss @@ -0,0 +1,5 @@ +@import './components'; + +@import './list'; +@import './search-bar'; + diff --git a/ui/packages/consul-peerings/app/components/consul/peer/list/README.mdx b/ui/packages/consul-peerings/app/components/consul/peer/list/README.mdx new file mode 100644 index 0000000000..f3a4694e5c --- /dev/null +++ b/ui/packages/consul-peerings/app/components/consul/peer/list/README.mdx @@ -0,0 +1,26 @@ +# Consul::Peer::List + +A presentational component for rendering Consul Peers + +```hbs preview-template + + + +``` + + +## Arguments + +| Argument/Attribute | Type | Default | Description | +| --- | --- | --- | --- | +| `items` | `array` | | An array of Peers | +| `ondelete` | `function` | | An action to execute when the `Delete` action is clicked | + +## See + +- [Template Source Code](./index.hbs) + +--- diff --git a/ui/packages/consul-peerings/app/components/consul/peer/list/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/list/index.hbs new file mode 100644 index 0000000000..249c5a9760 --- /dev/null +++ b/ui/packages/consul-peerings/app/components/consul/peer/list/index.hbs @@ -0,0 +1,93 @@ + + +{{#if (can 'delete peer' item=item)}} + + {{item.Name}} + +{{else}} +

+ {{item.Name}} +

+{{/if}} +
+ +
+ + +
+ {{t 'routes.dc.peers.index.detail.imported.count' + count=(format-number item.ImportedServiceCount) + }} +
+ +
+ {{t 'routes.dc.peers.index.detail.exported.count' + count=(format-number item.ExportedServiceCount) + }} +
+ +
+
+ +{{#if (can 'delete peer' item=item)}} + + + + + View + + + + + Delete + + + + + Confirm delete + + +

+ Are you sure you want to delete this peer? +

+
+ + + Delete + + +
+
+
+
+{{/if}} +
+
+ diff --git a/ui/packages/consul-peerings/app/components/consul/peer/notifications/README.mdx b/ui/packages/consul-peerings/app/components/consul/peer/notifications/README.mdx new file mode 100644 index 0000000000..a4a9fcc6d1 --- /dev/null +++ b/ui/packages/consul-peerings/app/components/consul/peer/notifications/README.mdx @@ -0,0 +1,19 @@ +# Consul::Peer::Notifications + +A Notification component specifically for Peers. This is only a component as we currently use this in two places and if we need to add more types we can do so in one place. + +We currently one have one 'remove' type due to the fact that Peers can't use the default 'delete' notification as they get 'marked for deletion' instead. + +```hbs preview-template + +``` + + + +## See + +- [Template Source Code](./index.hbs) + +--- diff --git a/ui/packages/consul-peerings/app/components/consul/peer/notifications/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/notifications/index.hbs new file mode 100644 index 0000000000..972c5c10e8 --- /dev/null +++ b/ui/packages/consul-peerings/app/components/consul/peer/notifications/index.hbs @@ -0,0 +1,16 @@ +{{#if (eq @type 'remove')}} + + + Success! + + +

+ Your Peer has been marked for deletion. +

+
+
+{{/if}} diff --git a/ui/packages/consul-ui/app/components/consul/peer/search-bar/README.mdx b/ui/packages/consul-peerings/app/components/consul/peer/search-bar/README.mdx similarity index 80% rename from ui/packages/consul-ui/app/components/consul/peer/search-bar/README.mdx rename to ui/packages/consul-peerings/app/components/consul/peer/search-bar/README.mdx index 2171a91f55..02b3fecf50 100644 --- a/ui/packages/consul-ui/app/components/consul/peer/search-bar/README.mdx +++ b/ui/packages/consul-peerings/app/components/consul/peer/search-bar/README.mdx @@ -8,12 +8,16 @@ Searchbar tailored for searching Peers. Follows our more generic @search={{this.search}} @onsearch={{fn (mut this.search) value="target.value"}} - @sort={{hash - value='Name:asc' + @sort={{hash + value='State:asc' change=(noop) }} @filter={{hash + state=(hash + value=(array "PENDING") + change=(noop) + ) searchproperty=(hash value=(array) change=(noop) diff --git a/ui/packages/consul-ui/app/components/consul/peer/search-bar/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/search-bar/index.hbs similarity index 64% rename from ui/packages/consul-ui/app/components/consul/peer/search-bar/index.hbs rename to ui/packages/consul-peerings/app/components/consul/peer/search-bar/index.hbs index 07b0ae51d1..17e75f5cd1 100644 --- a/ui/packages/consul-ui/app/components/consul/peer/search-bar/index.hbs +++ b/ui/packages/consul-peerings/app/components/consul/peer/search-bar/index.hbs @@ -64,6 +64,42 @@ as |key value|}} + <:filter as |search|> + + + + {{t "components.consul.peer.search-bar.state.name"}} + + + + {{#let components.Optgroup components.Option as |Optgroup Option|}} + {{#each + (get + (require '/models/peer' + export='schema' + from='/components/consul/peer/search-bar' + ) + 'State.allowedValues' + ) as |upperState|}} + {{#let + (string-to-lower-case upperState) + as |state|}} + + {{/let}} + {{/each}} + {{/let}} + + + <:sort as |search|> {{#let components.Optgroup components.Option as |Optgroup Option|}} + + + + diff --git a/ui/packages/consul-peerings/app/components/consul/peer/search-bar/index.scss b/ui/packages/consul-peerings/app/components/consul/peer/search-bar/index.scss new file mode 100644 index 0000000000..0e9e3c1ff2 --- /dev/null +++ b/ui/packages/consul-peerings/app/components/consul/peer/search-bar/index.scss @@ -0,0 +1,24 @@ +.consul-peer-search-bar { + li button span { + @extend %pill-500; + } + .value-pending span { + @extend %pill-pending; + } + .value-establishing span { + @extend %pill-establishing; + } + .value-active span { + @extend %pill-active; + } + .value-failing span { + @extend %pill-failing; + } + .value-terminated span { + @extend %pill-terminated; + } + .value-deleting span { + @extend %pill-deleting; + } +} + diff --git a/ui/packages/consul-peerings/app/components/consul/peer/selector/README.mdx b/ui/packages/consul-peerings/app/components/consul/peer/selector/README.mdx new file mode 100644 index 0000000000..e848296902 --- /dev/null +++ b/ui/packages/consul-peerings/app/components/consul/peer/selector/README.mdx @@ -0,0 +1,36 @@ +# Consul::Peer::Selector + +A conditional, autoloading, menu component specifically for navigating to peers. + +Please note: + +- Currently at least, you must add this inside of a `
    ` element. +- For the moment, make sure you have enabled peers using developer debug + cookies. + +```hbs preview-template +
      + +
    +``` + + +## Arguments + +| Argument/Attribute | Type | Default | Description | +| --- | --- | --- | --- | +| `dc` | `object` | | The current datacenter | +| `nspace` | `string` | | The name of the current namespace | +| `partition` | `string` | | The name of the current partition | + +## See + +- [Template Source Code](./index.hbs) + +--- diff --git a/ui/packages/consul-peerings/app/components/consul/peer/selector/index.hbs b/ui/packages/consul-peerings/app/components/consul/peer/selector/index.hbs new file mode 100644 index 0000000000..bccfb683b8 --- /dev/null +++ b/ui/packages/consul-peerings/app/components/consul/peer/selector/index.hbs @@ -0,0 +1,20 @@ + +
  • + + Peers + +
  • + diff --git a/ui/packages/consul-ui/app/templates/dc/peers/edit.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/edit.hbs similarity index 100% rename from ui/packages/consul-ui/app/templates/dc/peers/edit.hbs rename to ui/packages/consul-peerings/app/templates/dc/peers/edit.hbs diff --git a/ui/packages/consul-ui/app/templates/dc/peers/edit/addresses.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/edit/addresses.hbs similarity index 100% rename from ui/packages/consul-ui/app/templates/dc/peers/edit/addresses.hbs rename to ui/packages/consul-peerings/app/templates/dc/peers/edit/addresses.hbs diff --git a/ui/packages/consul-ui/app/templates/dc/peers/edit/index.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/edit/index.hbs similarity index 100% rename from ui/packages/consul-ui/app/templates/dc/peers/edit/index.hbs rename to ui/packages/consul-peerings/app/templates/dc/peers/edit/index.hbs diff --git a/ui/packages/consul-peerings/app/templates/dc/peers/index.hbs b/ui/packages/consul-peerings/app/templates/dc/peers/index.hbs new file mode 100644 index 0000000000..c9fd41e36c --- /dev/null +++ b/ui/packages/consul-peerings/app/templates/dc/peers/index.hbs @@ -0,0 +1,149 @@ + + + + + + + + +{{#let + + (hash + value=(or sortBy "State:asc") + change=(action (mut sortBy) value="target.selected") + ) + + (hash + state=(hash + value=(if state (split state ',') undefined) + change=(action (mut state) value="target.selectedItems") + ) + searchproperty=(hash + value=(if (not-eq searchproperty undefined) + (split searchproperty ',') + searchProperties + ) + change=(action (mut searchproperty) value="target.selectedItems") + default=searchProperties + ) + ) + + loader.data + +as |sort filters items|}} + + +

    + +

    +
    + + {{#if (gt items.length 0)}} + + {{/if}} + + + + + + + + + + + + + + + + {{!-- TODO: do we need to check permissions here or will we receive an error automatically? --}} + + +

    + {{#if (gt items.length 0)}} + No peers found + {{else}} + Welcome to Peers + {{/if}} +

    +
    + + {{#if (gt items.length 0)}} + No peers where found matching that search, or you may not have access to view the peers you are searching for. + {{else}} + Peering allows an admin partition in one datacenter to communicate with a partition in a different + datacenter. There don't seem to be any peers for this admin partition, or you may not have + peering:read permissions to + access this view. + {{/if}} + + + + + +
    +
    +
    +
    +
    +
    +
    +{{/let}} +
    +
    +
    diff --git a/ui/packages/consul-peerings/package.json b/ui/packages/consul-peerings/package.json new file mode 100644 index 0000000000..458d78a6e4 --- /dev/null +++ b/ui/packages/consul-peerings/package.json @@ -0,0 +1,5 @@ +{ + "name": "consul-peerings", + "version": "0.1.0", + "private": true +} diff --git a/ui/packages/consul-peerings/vendor/consul-peerings/routes.js b/ui/packages/consul-peerings/vendor/consul-peerings/routes.js new file mode 100644 index 0000000000..93b029ad3a --- /dev/null +++ b/ui/packages/consul-peerings/vendor/consul-peerings/routes.js @@ -0,0 +1,40 @@ +(routes => routes({ + dc: { + peers: { + _options: { + path: '/peers' + }, + index: { + _options: { + path: '/', + queryParams: { + sortBy: 'sort', + state: 'state', + searchproperty: { + as: 'searchproperty', + empty: [['Name']], + }, + search: { + as: 'filter', + replace: true, + }, + }, + }, + }, + edit: { + _options: { + path: '/:name' + }, + addresses: { + _options: { + path: '/addresses', + }, + }, + }, + }, + }, +}))( + (json, data = (typeof document !== 'undefined' ? document.currentScript.dataset : module.exports)) => { + data[`routes`] = JSON.stringify(json); + } +); diff --git a/ui/packages/consul-peerings/vendor/consul-peerings/services.js b/ui/packages/consul-peerings/vendor/consul-peerings/services.js new file mode 100644 index 0000000000..c5e069acca --- /dev/null +++ b/ui/packages/consul-peerings/vendor/consul-peerings/services.js @@ -0,0 +1,9 @@ +(services => services({ + "component:consul/peer/selector": { + "class": "consul-ui/components/consul/peer/selector" + } +}))( + (json, data = (typeof document !== 'undefined' ? document.currentScript.dataset : module.exports)) => { + data[`services`] = JSON.stringify(json); + } +); diff --git a/ui/packages/consul-ui/.docfy-config.js b/ui/packages/consul-ui/.docfy-config.js index 323469c843..0e1f6838ad 100644 --- a/ui/packages/consul-ui/.docfy-config.js +++ b/ui/packages/consul-ui/.docfy-config.js @@ -112,6 +112,12 @@ module.exports = { urlSchema: 'auto', urlPrefix: 'docs/consul-lock-sessions', }, + { + root: `${path.dirname(require.resolve('consul-peerings/package.json'))}/app/components`, + pattern: '**/README.mdx', + urlSchema: 'auto', + urlPrefix: 'docs/consul-peerings', + }, { root: `${path.dirname(require.resolve('consul-partitions/package.json'))}/app/components`, pattern: '**/README.mdx', diff --git a/ui/packages/consul-ui/app/abilities/peer.js b/ui/packages/consul-ui/app/abilities/peer.js index acd09956be..28b913a3e0 100644 --- a/ui/packages/consul-ui/app/abilities/peer.js +++ b/ui/packages/consul-ui/app/abilities/peer.js @@ -1,19 +1,23 @@ import BaseAbility from 'consul-ui/abilities/base'; +import { inject as service } from '@ember/service'; export default class PeerAbility extends BaseAbility { - resource = 'operator'; + @service('env') env; + + resource = 'peering'; segmented = false; get isLinkable() { return this.canDelete; } get canDelete() { - // TODO: Need to confirm these states return ![ 'DELETING', - 'TERMINATED', - 'UNDEFINED' - ].includes(this.item.State); + 'TERMINATED' + ].includes(this.item.State) && super.canDelete; } + get canUse() { + return this.env.var('CONSUL_PEERINGS_ENABLED'); + } } diff --git a/ui/packages/consul-ui/app/adapters/node.js b/ui/packages/consul-ui/app/adapters/node.js index 6df3b3b026..6e30108c7a 100644 --- a/ui/packages/consul-ui/app/adapters/node.js +++ b/ui/packages/consul-ui/app/adapters/node.js @@ -11,12 +11,12 @@ import { inject as service } from '@ember/service'; // to the node. export default class NodeAdapter extends Adapter { - @service features; + @service abilities; get peeringQuery() { const query = {}; - if (this.features.isEnabled('peering')) { + if (this.abilities.can('use peers')) { query['with-peers'] = true; } diff --git a/ui/packages/consul-ui/app/adapters/service.js b/ui/packages/consul-ui/app/adapters/service.js index d0dda48e46..7507c41b6b 100644 --- a/ui/packages/consul-ui/app/adapters/service.js +++ b/ui/packages/consul-ui/app/adapters/service.js @@ -2,12 +2,12 @@ import Adapter from './application'; import { inject as service } from '@ember/service'; export default class ServiceAdapter extends Adapter { - @service features; + @service abilities; get peeringQuery() { const query = {}; - if (this.features.isEnabled('peering')) { + if (this.abilities.can('use peers')) { query['with-peers'] = true; } diff --git a/ui/packages/consul-ui/app/components/certificate/README.mdx b/ui/packages/consul-ui/app/components/certificate/README.mdx deleted file mode 100644 index 34dd1bb359..0000000000 --- a/ui/packages/consul-ui/app/components/certificate/README.mdx +++ /dev/null @@ -1,31 +0,0 @@ -# Certificate - -```hbs preview-template - -``` - -### Arguments - -| Argument | Type | Default | Description | -| --- | --- | --- | --- | -| `item` | `String` | | The certificate as a string to be displayed and copied | -| `name` | `String` | | The 'Name' of the certificate to be displayed and copied. Mainly used for giving feedback to the user. | - -This component has the following: -- a copy button -- a visibility button to show and hide certificate -- a hidden and visible display of the certificate - -### See - -- [Component Source Code](./index.js) -- [Template Source Code](./index.hbs) - ---- diff --git a/ui/packages/consul-ui/app/components/certificate/index.hbs b/ui/packages/consul-ui/app/components/certificate/index.hbs deleted file mode 100644 index 8981db774c..0000000000 --- a/ui/packages/consul-ui/app/components/certificate/index.hbs +++ /dev/null @@ -1,14 +0,0 @@ -
    - - -{{#if this.show}} - {{@item}} -{{else}} -
    -{{/if}} -
    \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/certificate/index.js b/ui/packages/consul-ui/app/components/certificate/index.js deleted file mode 100644 index 3a8fdd17ea..0000000000 --- a/ui/packages/consul-ui/app/components/certificate/index.js +++ /dev/null @@ -1,14 +0,0 @@ -import Component from '@glimmer/component'; -import { tracked } from '@glimmer/tracking'; -import { action } from '@ember/object'; - -export default class Certificate extends Component { - // =attributes - @tracked show = false; - - // =actions - @action - setVisibility() { - this.show = !this.show; - } -} diff --git a/ui/packages/consul-ui/app/components/certificate/index.scss b/ui/packages/consul-ui/app/components/certificate/index.scss deleted file mode 100644 index f4a7ab23a9..0000000000 --- a/ui/packages/consul-ui/app/components/certificate/index.scss +++ /dev/null @@ -1,28 +0,0 @@ -.certificate { - display: flex; - button.visibility { - height: fit-content; - padding-top: 4px; - margin-right: 4px; - cursor: pointer; - } - button.hide::before { - @extend %with-visibility-hide-icon, %as-pseudo; - } - button.show::before { - @extend %with-visibility-show-icon, %as-pseudo; - } - code { - background-color: rgb(var(--tone-gray-050)); - overflow-wrap: break-word; - max-width: min-content; - padding: 0 12px; - } - hr { - border: 3px dashed rgb(var(--tone-gray-300)); - background-color: rgb(var(--tone-gray-000)); - width: 150px; - margin: auto; - margin-top: 9px; - } -} diff --git a/ui/packages/consul-ui/app/components/consul/auth-method/view/index.hbs b/ui/packages/consul-ui/app/components/consul/auth-method/view/index.hbs index e7f8f319c2..6dd5760064 100644 --- a/ui/packages/consul-ui/app/components/consul/auth-method/view/index.hbs +++ b/ui/packages/consul-ui/app/components/consul/auth-method/view/index.hbs @@ -13,23 +13,29 @@ {{#if @item.Config.Host}}
    {{t 'models.auth-method.Config.Host'}}
    - - {{@item.Config.Host}} +
    {{/if}} {{#if @item.Config.CACert}}
    {{t 'models.auth-method.Config.CACert'}}
    - +
    {{/if}} {{#if @item.Config.ServiceAccountJWT}}
    {{t 'models.auth-method.Config.ServiceAccountJWT'}}
    - - - {{@item.Config.ServiceAccountJWT}} - +
    {{/if}} @@ -96,25 +102,37 @@ as |item|}} {{#if @item.Config.JWKSURL}}
    {{t 'models.auth-method.Config.JWKSURL'}}
    - - {{@item.Config.JWKSURL}} +
    {{t 'models.auth-method.Config.JWKSCACert'}}
    - +
    {{/if}} {{#if @item.Config.JWTValidationPubKeys}}
    {{t 'models.auth-method.Config.JWTValidationPubKeys'}}
    - +
    {{/if}} {{#if @item.Config.OIDCDiscoveryURL}}
    {{t 'models.auth-method.Config.OIDCDiscoveryURL'}}
    - - {{@item.Config.OIDCDiscoveryURL}} +
    {{/if}} {{#if @item.Config.JWTSupportedAlgs}} @@ -143,14 +161,20 @@ as |item|}} {{#if @item.Config.OIDCDiscoveryURL}}
    {{t 'models.auth-method.Config.OIDCDiscoveryURL'}}
    - - {{@item.Config.OIDCDiscoveryURL}} +
    {{/if}} {{#if @item.Config.OIDCDiscoveryCACert}}
    {{t 'models.auth-method.Config.OIDCDiscoveryCACert'}}
    - +
    {{/if}} {{#if @item.Config.OIDCClientID}} @@ -167,8 +191,10 @@ as |item|}}
      {{#each @item.Config.AllowedRedirectURIs as |uri|}}
    • - - {{uri}} +
    • {{/each}}
    diff --git a/ui/packages/consul-ui/app/styles/routes/dc/peers/index.scss b/ui/packages/consul-ui/app/components/consul/peer/list/index.scss similarity index 79% rename from ui/packages/consul-ui/app/styles/routes/dc/peers/index.scss rename to ui/packages/consul-ui/app/components/consul/peer/list/index.scss index 1380b3ab18..a20a2cbcdd 100644 --- a/ui/packages/consul-ui/app/styles/routes/dc/peers/index.scss +++ b/ui/packages/consul-ui/app/components/consul/peer/list/index.scss @@ -1,6 +1,6 @@ .peers__list__peer-detail { display: flex; align-content: center; - overflow-x: scroll; gap: 18px; } + diff --git a/ui/packages/consul-ui/app/components/copyable-code/README.mdx b/ui/packages/consul-ui/app/components/copyable-code/README.mdx new file mode 100644 index 0000000000..a7cc0caf99 --- /dev/null +++ b/ui/packages/consul-ui/app/components/copyable-code/README.mdx @@ -0,0 +1,50 @@ +# CopyableCode + +CopyableCode is used to display code that is likely to be copied by the user. + +It also has an option to obfuscate the code, that is then toggleable by the user. + +Text within the component is formatted using a `
    ` tag.
    +
    +```hbs preview-template
    +
    +
    Without obfuscation
    + +
    +``` + +```hbs preview-template +
    +
    With obfuscation
    + +
    +``` + +### Arguments + +| Argument | Type | Default | Description | +| --- | --- | --- | --- | +| `value` | `String` | | The code to display/be copied | +| `name` | `String` | | The 'Name' of the thing to be displayed and copied. Mainly used for giving feedback to the user. | +| `obfuscated` | `boolean` | | Whether to obfuscate the value until the user clicks to view | + +### See + +- [Template Source Code](./index.hbs) + +--- diff --git a/ui/packages/consul-ui/app/components/copyable-code/index.hbs b/ui/packages/consul-ui/app/components/copyable-code/index.hbs new file mode 100644 index 0000000000..00ae9ea8c0 --- /dev/null +++ b/ui/packages/consul-ui/app/components/copyable-code/index.hbs @@ -0,0 +1,45 @@ +
    +{{#if @obfuscated}} + + + + + +
    {{@value}}
    +
    + + {{#if (not details.expanded)}} +
    + {{/if}} +
    +
    + + + +{{else}} +
    {{@value}}
    + +{{/if}} + +
    \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/copyable-code/index.scss b/ui/packages/consul-ui/app/components/copyable-code/index.scss new file mode 100644 index 0000000000..7745aadb68 --- /dev/null +++ b/ui/packages/consul-ui/app/components/copyable-code/index.scss @@ -0,0 +1,65 @@ +.copyable-code { + & { + display: flex; + align-items: flex-start; + position: relative; + width: 100%; + padding: 8px 14px; + padding-bottom: 3px; + + border: var(--decor-border-100); + border-color: rgb(var(--tone-gray-200)); + border-radius: var(--decor-radius-200); + } + &.obfuscated { + padding-left: 4px; + } + &::after { + position: absolute; + top: 0; + right: 0; + width: 40px; + height: 100%; + display: block; + content: ''; + background-color: rgb(var(--tone-gray-050)); + } + .copy-button { + position: absolute; + top: 7px; + right: 12px; + } + button[aria-expanded] { + margin-top: 1px; + margin-right: 4px; + cursor: pointer; + } + button[aria-expanded]::before { + content: ''; + --icon-size: icon-000; + --icon-color: rgb(var(--tone-gray-500)); + } + button[aria-expanded=true]::before { + --icon-name: icon-eye-off; + } + button[aria-expanded=false]::before { + --icon-name: icon-eye; + } + pre { + padding-right: 30px; + } + code { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + } + hr { + width: calc(100% - 80px); + margin: 0; + margin-top: 8px; + margin-bottom: 13px; + border: 3px dashed rgb(var(--tone-gray-300)); + background-color: rgb(var(--tone-gray-000)); + } +} diff --git a/ui/packages/consul-ui/app/components/data-loader/README.mdx b/ui/packages/consul-ui/app/components/data-loader/README.mdx index c2b6383e2a..f9db81f246 100644 --- a/ui/packages/consul-ui/app/components/data-loader/README.mdx +++ b/ui/packages/consul-ui/app/components/data-loader/README.mdx @@ -48,12 +48,13 @@ as |loader|> | --- | --- | --- | --- | | `src` | `String` | | The source to subscribe to updates to, this should map to a string based URI | -## Exports +## Exported API -| Name | Description | -| --- | --- | -| `data` | The loaded dataset once any data has been loaded successfully | -| `error` | The error thrown if an error is encountered whilst loading data | +| Name | Type | Description | +| --- | --- | --- | +| `data` | `object` | The loaded dataset once any data has been loaded successfully | +| `error` | `Error` |The error thrown if an error is encountered whilst loading data | +| `invalidate` | `function` | Invalidate the data represented by the DataLoader, therefore forcing a re-request of data for the DataLoader | ## Slots diff --git a/ui/packages/consul-ui/app/components/data-loader/chart.xstate.js b/ui/packages/consul-ui/app/components/data-loader/chart.xstate.js index dde7c5349c..94cc961316 100644 --- a/ui/packages/consul-ui/app/components/data-loader/chart.xstate.js +++ b/ui/packages/consul-ui/app/components/data-loader/chart.xstate.js @@ -17,15 +17,9 @@ export default { target: 'loading', }, ], - INVALIDATE: [ - { - target: 'invalidating', - }, - ], }, states: { load: {}, - invalidating: {}, loading: { on: { SUCCESS: { diff --git a/ui/packages/consul-ui/app/components/data-loader/index.hbs b/ui/packages/consul-ui/app/components/data-loader/index.hbs index 6f38827ab4..6be3fd61c6 100644 --- a/ui/packages/consul-ui/app/components/data-loader/index.hbs +++ b/ui/packages/consul-ui/app/components/data-loader/index.hbs @@ -7,7 +7,7 @@ {{#let (hash data=data error=error - invalidate=(action "invalidate") + invalidate=this.invalidate dispatchError=(queue (action (mut error) value="error.errors.firstObject") (action dispatch "ERROR")) ) as |api|}} @@ -17,7 +17,7 @@ {{! if we didn't specify any data}} {{#if (not items)}} {{! try and load the data if we aren't in an error state}} - + {{! but only if we only asked for a single load and we are in loading state}} {{#if (and src (or (not once) (state-matches state "loading")))}} + as |source|> + {{did-insert (set this 'invalidate' source.invalidate)}} + {{/if}} {{/if}} @@ -47,7 +49,7 @@ {{/yield-slot}} - + {{#if (not (eq error.status '401'))}} diff --git a/ui/packages/consul-ui/app/components/data-loader/index.js b/ui/packages/consul-ui/app/components/data-loader/index.js index 0039ba3d49..19967a12ac 100644 --- a/ui/packages/consul-ui/app/components/data-loader/index.js +++ b/ui/packages/consul-ui/app/components/data-loader/index.js @@ -1,6 +1,5 @@ import Component from '@ember/component'; import { set } from '@ember/object'; -import { schedule } from '@ember/runloop'; import Slotted from 'block-slots'; import chart from './chart.xstate'; @@ -22,12 +21,6 @@ export default Component.extend(Slotted, { this.dispatch('LOAD'); }, actions: { - invalidate() { - this.dispatch('INVALIDATE'); - schedule('afterRender', () => { - this.dispatch('LOAD'); - }); - }, isLoaded: function() { return typeof this.items !== 'undefined' || typeof this.src === 'undefined'; }, diff --git a/ui/packages/consul-ui/app/components/data-source/README.mdx b/ui/packages/consul-ui/app/components/data-source/README.mdx index 559eff6bbc..adc8fcba2b 100644 --- a/ui/packages/consul-ui/app/components/data-source/README.mdx +++ b/ui/packages/consul-ui/app/components/data-source/README.mdx @@ -40,6 +40,14 @@ Please make sure you use the `uri` helper to specify src URIs, this ensures that | `onchange` | `Function` | | The action to fire when the data changes. Emits an Event-like object with a `data` property containing the data. | | `onerror` | `Function` | | The action to fire when an error occurs. Emits ErrorEvent object with an `error` property containing the Error. | +## Exported API + +| Name | Type | Description | +| --- | --- | --- | +| `data` | `object` | The loaded dataset once any data has been loaded successfully | +| `error` | `Error` |The error thrown if an error is encountered whilst loading data | +| `invalidate` | `function` | Invalidate the data represented by the datasource, therefore forcing a re-request of data for the DataSource | + The component takes a `src` or an identifier (a uri) for some data and then emits `onchange` events whenever that data changes. If an error occurs whilst listening for data changes, an `onerror` event is emitted. Setting `@loading="lazy"` uses `IntersectionObserver` to activate/deactive event emitting until the `` element is displayed in the DOM. This means you can use CSS `display: none|block;` to control the loading and stopping loading of data for usage with CSS based tabs and such-like. diff --git a/ui/packages/consul-ui/app/components/data-source/index.hbs b/ui/packages/consul-ui/app/components/data-source/index.hbs index de3b6c8de9..d4b1e2613c 100644 --- a/ui/packages/consul-ui/app/components/data-source/index.hbs +++ b/ui/packages/consul-ui/app/components/data-source/index.hbs @@ -17,6 +17,7 @@ {{yield (hash data=this.data error=this.error + invalidate=this.invalidate Source=(if this.data (component 'data-source' disabled=(not (eq this.error undefined))) '' diff --git a/ui/packages/consul-ui/app/components/data-source/index.js b/ui/packages/consul-ui/app/components/data-source/index.js index f854cc9f05..3d5d66ebdf 100644 --- a/ui/packages/consul-ui/app/components/data-source/index.js +++ b/ui/packages/consul-ui/app/components/data-source/index.js @@ -1,3 +1,4 @@ +/* eslint no-console: ["error", { allow: ["debug"] }] */ import Component from '@glimmer/component'; import { inject as service } from '@ember/service'; import { tracked } from '@glimmer/tracking'; @@ -179,6 +180,7 @@ export default class DataSource extends Component { } } } + @action async invalidate() { this.source.readyState = 2; @@ -186,7 +188,7 @@ export default class DataSource extends Component { schedule('afterRender', () => { // TODO: Support lazy data-sources by keeping a reference to $el runInDebug(_ => - console.error( + console.debug( `Invalidation is only supported for non-lazy data sources. If you want to use this you should fixup support for lazy data sources` ) ); diff --git a/ui/packages/consul-ui/app/components/definition-table/README.mdx b/ui/packages/consul-ui/app/components/definition-table/README.mdx index 971b59ee7b..390a49ed93 100644 --- a/ui/packages/consul-ui/app/components/definition-table/README.mdx +++ b/ui/packages/consul-ui/app/components/definition-table/README.mdx @@ -4,7 +4,6 @@ class: css # definition-table Simple CSS component to render a `dl` similar to a table with column headers. -Contents of the `dd` are currently inline-block'ed for CopyButton reasons. ```hbs preview-template
    @@ -12,7 +11,12 @@ Contents of the `dd` are currently inline-block'ed for CopyButton reasons.
    Title 1
    Value
    Title 2
    -
    Value
    +
    + +
    ``` diff --git a/ui/packages/consul-ui/app/components/definition-table/layout.scss b/ui/packages/consul-ui/app/components/definition-table/layout.scss index 3173fe1759..db0c27e90b 100644 --- a/ui/packages/consul-ui/app/components/definition-table/layout.scss +++ b/ui/packages/consul-ui/app/components/definition-table/layout.scss @@ -6,10 +6,3 @@ %definition-table > dl { margin-bottom: 1.4em; } -/* TODO: We currently have one instance of nested dls */ -/* and that is for nesting a bucket list */ -/* we should probably think about changing this to possibly inline flex */ -/* or individually styling the contents */ -%definition-table > dl > dd > *:not(dl) { - display: inline-block; -} diff --git a/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs b/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs index 2a98a76853..07296d4fe1 100644 --- a/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs +++ b/ui/packages/consul-ui/app/components/hashicorp-consul/index.hbs @@ -146,14 +146,11 @@ @partition={{@partition}} @nspace={{@nspace}} /> - {{#if (feature-flag "peering")}} -
  • - Organization -
  • -
  • - Peers -
  • - {{/if}} +
diff --git a/ui/packages/consul-ui/app/components/secret-button/index.hbs b/ui/packages/consul-ui/app/components/secret-button/index.hbs deleted file mode 100644 index 539810f735..0000000000 --- a/ui/packages/consul-ui/app/components/secret-button/index.hbs +++ /dev/null @@ -1,5 +0,0 @@ - \ No newline at end of file diff --git a/ui/packages/consul-ui/app/components/secret-button/index.js b/ui/packages/consul-ui/app/components/secret-button/index.js deleted file mode 100644 index 5570647734..0000000000 --- a/ui/packages/consul-ui/app/components/secret-button/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import Component from '@ember/component'; - -export default Component.extend({}); diff --git a/ui/packages/consul-ui/app/components/secret-button/index.scss b/ui/packages/consul-ui/app/components/secret-button/index.scss deleted file mode 100644 index aafd0b9423..0000000000 --- a/ui/packages/consul-ui/app/components/secret-button/index.scss +++ /dev/null @@ -1,23 +0,0 @@ -@import './skin'; -@import './layout'; -.type-reveal { - @extend %secret-button; -} -%secret-button { - position: relative; -} -%secret-button span { - visibility: hidden; - position: absolute; - --icon-color: rgb(var(--tone-gray-500)); -} -%secret-button em { - margin-left: 22px; -} -%secret-button span::before { - @extend %with-visibility-show-mask, %as-pseudo; - visibility: visible; -} -%secret-button input:checked + span::before { - @extend %with-visibility-hide-mask; -} diff --git a/ui/packages/consul-ui/app/components/secret-button/layout.scss b/ui/packages/consul-ui/app/components/secret-button/layout.scss deleted file mode 100644 index 1393e5efeb..0000000000 --- a/ui/packages/consul-ui/app/components/secret-button/layout.scss +++ /dev/null @@ -1,23 +0,0 @@ -%secret-button { - cursor: pointer; -} -%secret-button input { - display: none; -} -%secret-button input ~ em { - visibility: hidden; - font-style: normal; -} -%secret-button input:checked ~ em { - @extend %user-select-text; - visibility: visible; - cursor: auto; -} -%secret-button input ~ em::before { - display: inline; - visibility: visible; - content: '■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■'; -} -%secret-button input:checked ~ em::before { - display: none; -} diff --git a/ui/packages/consul-ui/app/components/secret-button/skin.scss b/ui/packages/consul-ui/app/components/secret-button/skin.scss deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/ui/packages/consul-ui/app/components/tab-nav/README.mdx b/ui/packages/consul-ui/app/components/tab-nav/README.mdx index 46fb498c51..49454df5da 100644 --- a/ui/packages/consul-ui/app/components/tab-nav/README.mdx +++ b/ui/packages/consul-ui/app/components/tab-nav/README.mdx @@ -11,14 +11,21 @@ Each item in the list should be a hash of `label`, `href` and `selected`. - `label`: The text to show - `href`: a href, probably generated via `href-to` - `selected`: whether the item is in the selected state or not, probably - generated via `is-href` + of the state to transition to. + +There are two similar event handlers, `@onclick` and `@onTabClick`. + +When using `@onclick`, the `item.label` is passed to the handler. When using +`@onTabClick` the entire 'item' is passed instead, therefore you can add +arbitrary properties to the 'item' to be used in the handler. + **Please note:** This component should probably be rebuilt using contextual -components, alternatively this could be hand built with native HTML using the -same `nav/ul/li/a` pattern and you could just use the CSS component to style -it. Unless there is a reason to do this, this component should be used pending -a refactor (please remove this note once refactored into contextual -components) +components, and real events. Alternatively this could be hand built with native +HTML using the same `nav/ul/li/a` pattern and you could just use the CSS +component to style it. Unless there is a reason to do this, this component +should be used pending a refactor (please remove this note once refactored into +contextual components) ```hbs preview-template
@@ -36,6 +43,31 @@ components)
``` +A TabNav with using a `StateMachine.dispatch` + +```hbs +
+
A TabNav with using a StateMachine.dispatch
+ +
+``` + ```css .tab-nav { @extend %tab-nav; diff --git a/ui/packages/consul-ui/app/components/tab-nav/index.hbs b/ui/packages/consul-ui/app/components/tab-nav/index.hbs index 818703e20c..fc6da077b9 100644 --- a/ui/packages/consul-ui/app/components/tab-nav/index.hbs +++ b/ui/packages/consul-ui/app/components/tab-nav/index.hbs @@ -36,6 +36,12 @@ as |select name|}} (noop) ) }} + {{on 'click' + (if @onTabClicked + (fn @onTabClicked item) + (noop) + ) + }} @href={{item.href}} > {{item.label}} diff --git a/ui/packages/consul-ui/app/components/tabular-dl/layout.scss b/ui/packages/consul-ui/app/components/tabular-dl/layout.scss index edeb482a47..3e8d6b4223 100644 --- a/ui/packages/consul-ui/app/components/tabular-dl/layout.scss +++ b/ui/packages/consul-ui/app/components/tabular-dl/layout.scss @@ -25,10 +25,6 @@ dd > ul li:not(:last-of-type) { padding-bottom: 12px; } - dd .copy-button button { - padding: 0 !important; - margin: 0 4px 0 0 !important; - } dt.check + dd { padding-top: 16px; } diff --git a/ui/packages/consul-ui/app/filter/predicates/peer.js b/ui/packages/consul-ui/app/filter/predicates/peer.js new file mode 100644 index 0000000000..7bafa7fa2c --- /dev/null +++ b/ui/packages/consul-ui/app/filter/predicates/peer.js @@ -0,0 +1,10 @@ +export default { + state: { + pending: (item, value) => item.State.toLowerCase() === value, + establishing: (item, value) => item.State.toLowerCase() === value, + active: (item, value) => item.State.toLowerCase() === value, + failing: (item, value) => item.State.toLowerCase() === value, + terminated: (item, value) => item.State.toLowerCase() === value, + deleting: (item, value) => item.State.toLowerCase() === value, + }, +}; diff --git a/ui/packages/consul-ui/app/helpers/feature-flag.js b/ui/packages/consul-ui/app/helpers/feature-flag.js deleted file mode 100644 index bf5c273187..0000000000 --- a/ui/packages/consul-ui/app/helpers/feature-flag.js +++ /dev/null @@ -1,10 +0,0 @@ -import Helper from '@ember/component/helper'; -import { inject as service } from '@ember/service'; - -export default class extends Helper { - @service features; - - compute([feature]) { - return this.features.isEnabled(feature); - } -} diff --git a/ui/packages/consul-ui/app/helpers/require.js b/ui/packages/consul-ui/app/helpers/require.js index 59f3606586..c3b39e869f 100644 --- a/ui/packages/consul-ui/app/helpers/require.js +++ b/ui/packages/consul-ui/app/helpers/require.js @@ -12,12 +12,15 @@ const container = new Map(); // `css` already has a caching mechanism under the hood so rely on that, plus // we get the advantage of laziness here, i.e. we only call css as and when we // need to -export default helper(([path = ''], { from }) => { - const fullPath = resolve(`${appName}${from}`, path); +export default helper(([path = ''], options) => { + let fullPath = resolve(`${appName}${options.from}`, path); + if(path.charAt(0) === '/') { + fullPath = `${appName}${fullPath}`; + } let module; if(require.has(fullPath)) { - module = require(fullPath).default; + module = require(fullPath)[options.export || 'default']; } else { throw new Error(`Unable to resolve '${fullPath}' does the file exist?`) } @@ -27,7 +30,7 @@ export default helper(([path = ''], { from }) => { return module(css); case fullPath.endsWith('.xstate'): return module; - default: { + case fullPath.endsWith('.element'): { if(container.has(fullPath)) { return container.get(fullPath); } @@ -35,5 +38,7 @@ export default helper(([path = ''], { from }) => { container.set(fullPath, component); return component; } + default: + return module; } }); diff --git a/ui/packages/consul-ui/app/models/peer.js b/ui/packages/consul-ui/app/models/peer.js index 89c70177e1..5b2c6a01ad 100644 --- a/ui/packages/consul-ui/app/models/peer.js +++ b/ui/packages/consul-ui/app/models/peer.js @@ -1,5 +1,18 @@ import Model, { attr } from '@ember-data/model'; +export const schema = { + State: { + defaultValue: 'PENDING', + allowedValues: [ + 'PENDING', + 'ESTABLISHING', + 'ACTIVE', + 'FAILING', + 'TERMINATED', + 'DELETING' + ], + }, +}; export default class Peer extends Model { @attr('string') uri; @attr() meta; diff --git a/ui/packages/consul-ui/app/routes/dc/peers.js b/ui/packages/consul-ui/app/routes/dc/peers.js deleted file mode 100644 index 195d1e2a18..0000000000 --- a/ui/packages/consul-ui/app/routes/dc/peers.js +++ /dev/null @@ -1,12 +0,0 @@ -import { inject as service } from '@ember/service'; -import Route from '@ember/routing/route'; - -export default class PeersRoute extends Route { - @service features; - - beforeModel() { - if (!this.features.isEnabled('peering')) { - this.transitionTo('dc.services.index'); - } - } -} diff --git a/ui/packages/consul-ui/app/routes/dc/peers/index.js b/ui/packages/consul-ui/app/routes/dc/peers/index.js deleted file mode 100644 index 5b0973e293..0000000000 --- a/ui/packages/consul-ui/app/routes/dc/peers/index.js +++ /dev/null @@ -1,15 +0,0 @@ -import Route from 'consul-ui/routing/route'; - -export default class PeersRoute extends Route { - queryParams = { - sortBy: 'sort', - searchproperty: { - as: 'searchproperty', - empty: [['Name']], - }, - search: { - as: 'filter', - replace: true, - }, - }; -} diff --git a/ui/packages/consul-ui/app/services/data-sink/protocols/http.js b/ui/packages/consul-ui/app/services/data-sink/protocols/http.js index 21467648be..9a99eb796f 100644 --- a/ui/packages/consul-ui/app/services/data-sink/protocols/http.js +++ b/ui/packages/consul-ui/app/services/data-sink/protocols/http.js @@ -2,11 +2,14 @@ import Service, { inject as service } from '@ember/service'; import { setProperties } from '@ember/object'; export default class HttpService extends Service { + @service('client/http') client; + @service('settings') settings; @service('repository/intention') intention; @service('repository/kv') kv; @service('repository/nspace') nspace; @service('repository/partition') partition; + @service('repository/peer') peer; @service('repository/session') session; prepare(sink, data, instance) { @@ -24,12 +27,16 @@ export default class HttpService extends Service { persist(sink, instance) { const [, , , , model] = sink.split('/'); const repo = this[model]; - return repo.persist(instance); + return this.client.request( + request => repo.persist(instance, request) + ); } remove(sink, instance) { const [, , , , model] = sink.split('/'); const repo = this[model]; - return repo.remove(instance); + return this.client.request( + request => repo.remove(instance, request) + ); } } diff --git a/ui/packages/consul-ui/app/services/features.js b/ui/packages/consul-ui/app/services/features.js deleted file mode 100644 index bbfc53748b..0000000000 --- a/ui/packages/consul-ui/app/services/features.js +++ /dev/null @@ -1,13 +0,0 @@ -import Service, { inject as service } from '@ember/service'; - -export default class FeatureService extends Service { - @service env; - - get features() { - return this.env.var('features'); - } - - isEnabled(featureName) { - return !!this.features?.[featureName]; - } -} diff --git a/ui/packages/consul-ui/app/services/filter.js b/ui/packages/consul-ui/app/services/filter.js index 1ba36ec48a..bf78151a7e 100644 --- a/ui/packages/consul-ui/app/services/filter.js +++ b/ui/packages/consul-ui/app/services/filter.js @@ -10,6 +10,7 @@ import intention from 'consul-ui/filter/predicates/intention'; import token from 'consul-ui/filter/predicates/token'; import policy from 'consul-ui/filter/predicates/policy'; import authMethod from 'consul-ui/filter/predicates/auth-method'; +import peer from 'consul-ui/filter/predicates/peer'; const predicates = { service: andOr(service), @@ -21,6 +22,7 @@ const predicates = { intention: andOr(intention), token: andOr(token), policy: andOr(policy), + peer: andOr(peer), }; export default class FilterService extends Service { diff --git a/ui/packages/consul-ui/app/services/repository/peer.js b/ui/packages/consul-ui/app/services/repository/peer.js index 5154a72500..1062ed2b69 100644 --- a/ui/packages/consul-ui/app/services/repository/peer.js +++ b/ui/packages/consul-ui/app/services/repository/peer.js @@ -7,6 +7,19 @@ export default class PeerService extends RepositoryService { return 'peer'; } + @dataSource('/:partition/:ns/:dc/peering/token-for/:name') + async fetchToken({dc, ns, partition, name}, configuration, request) { + return (await request` + POST /v1/peering/token + + ${{ + PeerName: name, + Datacenter: dc, + Partition: partition || undefined, + }} + `)((headers, body, cache) => body) + } + @dataSource('/:partition/:ns/:dc/peers') async fetchAll({ dc, ns, partition }, { uri }, request) { return (await request` @@ -70,4 +83,61 @@ export default class PeerService extends RepositoryService { }; }); } + + async persist(item, request) { + // mark it as ESTABLISHING ourselves as the request is successful + // and we don't have blocking queries here to get immediate updates + return (await request` + POST /v1/peering/establish + + ${{ + PeerName: item.Name, + PeeringToken: item.PeeringToken, + Datacenter: item.Datacenter, + Partition: item.Partition || undefined, + }} + `)((headers, body, cache) => { + const partition = item.Partition; + const ns = item.Namespace; + const dc = item.Datacenter; + return { + meta: { + version: 2, + }, + body: cache( + { + ...item, + State: 'ESTABLISHING' + }, + uri => uri`peer:///${partition}/${ns}/${dc}/peer/${item.Name}` + ) + }; + }); + } + + async remove(item, request) { + // soft delete + // we just return the item we want to delete + // but mark it as DELETING ourselves as the request is successful + // and we don't have blocking queries here to get immediate updates + return (await request` + DELETE /v1/peering/${item.Name} + `)((headers, body, cache) => { + const partition = item.Partition; + const ns = item.Namespace; + const dc = item.Datacenter; + return { + meta: { + version: 2, + }, + body: cache( + { + ...item, + State: 'DELETING' + }, + uri => uri`peer:///${partition}/${ns}/${dc}/peer/${item.Name}` + ) + }; + }); + } } diff --git a/ui/packages/consul-ui/app/services/repository/permission.js b/ui/packages/consul-ui/app/services/repository/permission.js index 08c96e3e4a..8b15ddd1bf 100644 --- a/ui/packages/consul-ui/app/services/repository/permission.js +++ b/ui/packages/consul-ui/app/services/repository/permission.js @@ -57,6 +57,16 @@ const REQUIRED_PERMISSIONS = [ Access: 'write', }, ]; +const PEERING_PERMISSIONS = [ + { + Resource: 'peering', + Access: 'read', + }, + { + Resource: 'peering', + Access: 'write', + }, +]; export default class PermissionService extends RepositoryService { @service('env') env; @service('abilities') _can; @@ -146,7 +156,7 @@ export default class PermissionService extends RepositoryService { @dataSource('/:partition/:nspace/:dc/permissions') async findAll(params) { - params.resources = REQUIRED_PERMISSIONS; + params.resources = this.permissionsToRequest; this.permissions = await this.findByPermissions(params); /**/ // Temporarily revert to pre-1.10 UI functionality by overwriting frontend @@ -162,4 +172,12 @@ export default class PermissionService extends RepositoryService { /**/ return this.permissions; } + + get permissionsToRequest() { + if (this._can.can('use peers')) { + return [...REQUIRED_PERMISSIONS, ...PEERING_PERMISSIONS]; + } else { + return REQUIRED_PERMISSIONS; + } + } } diff --git a/ui/packages/consul-ui/app/sort/comparators/peer.js b/ui/packages/consul-ui/app/sort/comparators/peer.js index 1ec2b1a99c..912d231403 100644 --- a/ui/packages/consul-ui/app/sort/comparators/peer.js +++ b/ui/packages/consul-ui/app/sort/comparators/peer.js @@ -1,3 +1,26 @@ -export default ({ properties }) => key => { +import { schema } from 'consul-ui/models/peer'; + +export default ({ properties }) => (key = 'State:asc') => { + if (key.startsWith('State:')) { + return function(itemA, itemB) { + const [, dir] = key.split(':'); + let a, b; + if (dir === 'asc') { + b = itemA; + a = itemB; + } else { + a = itemA; + b = itemB; + } + switch (true) { + case schema.State.allowedValues.indexOf(a.State) < schema.State.allowedValues.indexOf(b.State): + return 1; + case schema.State.allowedValues.indexOf(a.State) > schema.State.allowedValues.indexOf(b.State): + return -1; + case schema.State.allowedValues.indexOf(a.State) === schema.State.allowedValues.indexOf(b.State): + return 0; + } + }; + } return properties(['Name'])(key); }; diff --git a/ui/packages/consul-ui/app/styles/base/icons/icons/index.scss b/ui/packages/consul-ui/app/styles/base/icons/icons/index.scss index 4ba418ad65..74559e892f 100644 --- a/ui/packages/consul-ui/app/styles/base/icons/icons/index.scss +++ b/ui/packages/consul-ui/app/styles/base/icons/icons/index.scss @@ -154,8 +154,8 @@ // @import './user-square-fill/index.scss'; // @import './user-square-outline/index.scss'; @import './user-team/index.scss'; -@import './visibility-hide/index.scss'; -@import './visibility-show/index.scss'; +// @import './visibility-hide/index.scss'; +// @import './visibility-show/index.scss'; // @import './webhook/index.scss'; // @import './activity/index.scss'; @import './alert-circle/index.scss'; @@ -316,8 +316,8 @@ // @import './event/index.scss'; // @import './exit-point/index.scss'; // @import './external-link/index.scss'; -// @import './eye/index.scss'; -// @import './eye-off/index.scss'; +@import './eye/index.scss'; +@import './eye-off/index.scss'; // @import './f5/index.scss'; // @import './f5-color/index.scss'; // @import './facebook/index.scss'; @@ -501,7 +501,7 @@ // @import './rotate-ccw/index.scss'; // @import './rotate-cw/index.scss'; // @import './rss/index.scss'; -// @import './running/index.scss'; +@import './running/index.scss'; // @import './save/index.scss'; // @import './scissors/index.scss'; // @import './search/index.scss'; @@ -620,7 +620,7 @@ // @import './x-diamond-fill/index.scss'; // @import './x-hexagon/index.scss'; // @import './x-hexagon-fill/index.scss'; -// @import './x-square/index.scss'; +@import './x-square/index.scss'; // @import './x-square-fill/index.scss'; // @import './youtube/index.scss'; // @import './youtube-color/index.scss'; diff --git a/ui/packages/consul-ui/app/styles/components.scss b/ui/packages/consul-ui/app/styles/components.scss index 73ed5fcf13..234b6793a0 100644 --- a/ui/packages/consul-ui/app/styles/components.scss +++ b/ui/packages/consul-ui/app/styles/components.scss @@ -33,7 +33,6 @@ @import 'consul-ui/components/popover-select'; @import 'consul-ui/components/progress'; @import 'consul-ui/components/radio-group'; -@import 'consul-ui/components/secret-button'; @import 'consul-ui/components/sliding-toggle'; @import 'consul-ui/components/table'; @import 'consul-ui/components/tile'; @@ -75,7 +74,7 @@ @import 'consul-ui/components/informed-action'; @import 'consul-ui/components/tab-nav'; @import 'consul-ui/components/search-bar'; -@import 'consul-ui/components/certificate'; +@import 'consul-ui/components/copyable-code'; @import 'consul-ui/components/consul/loader'; @import 'consul-ui/components/consul/tomography/graph'; @@ -104,7 +103,8 @@ @import 'consul-ui/components/topology-metrics/series'; @import 'consul-ui/components/topology-metrics/stats'; @import 'consul-ui/components/topology-metrics/status'; +@import 'consul-ui/components/consul/intention/list/table'; +@import 'consul-ui/components/consul/peer'; @import 'consul-ui/components/peerings/badge'; @import 'consul-ui/components/consul/node/peer-info'; -@import 'consul-ui/components/consul/intention/list/table'; @import 'consul-ui/components/consul/service/peer-info'; diff --git a/ui/packages/consul-ui/app/styles/debug.scss b/ui/packages/consul-ui/app/styles/debug.scss index 8209e6ac4e..66cecc7ed3 100644 --- a/ui/packages/consul-ui/app/styles/debug.scss +++ b/ui/packages/consul-ui/app/styles/debug.scss @@ -252,9 +252,6 @@ html.with-route-announcer .route-title { figcaption code { @extend %inline-code; } - pre code { - @extend %block-code; - } figure > [type='text'] { border: 1px solid rgb(var(--tone-gray-999)); width: 100%; diff --git a/ui/packages/consul-ui/app/styles/routes.scss b/ui/packages/consul-ui/app/styles/routes.scss index 0493242c3f..624ff4570c 100644 --- a/ui/packages/consul-ui/app/styles/routes.scss +++ b/ui/packages/consul-ui/app/styles/routes.scss @@ -5,4 +5,3 @@ @import 'routes/dc/intentions/index'; @import 'routes/dc/overview/serverstatus'; @import 'routes/dc/overview/license'; -@import 'routes/dc/peers'; diff --git a/ui/packages/consul-ui/app/templates/dc/acls/policies/edit.hbs b/ui/packages/consul-ui/app/templates/dc/acls/policies/edit.hbs index b1480fbb32..63cc8ea667 100644 --- a/ui/packages/consul-ui/app/templates/dc/acls/policies/edit.hbs +++ b/ui/packages/consul-ui/app/templates/dc/acls/policies/edit.hbs @@ -62,7 +62,10 @@ as |dc partition nspace id item create|}}
Policy ID
- {{item.ID}} +
diff --git a/ui/packages/consul-ui/app/templates/dc/acls/roles/edit.hbs b/ui/packages/consul-ui/app/templates/dc/acls/roles/edit.hbs index 00202a4057..8caa4ff094 100644 --- a/ui/packages/consul-ui/app/templates/dc/acls/roles/edit.hbs +++ b/ui/packages/consul-ui/app/templates/dc/acls/roles/edit.hbs @@ -56,7 +56,10 @@ as |dc partition nspace item create|}}
Role ID
- {{item.ID}} +
diff --git a/ui/packages/consul-ui/app/templates/dc/acls/tokens/edit.hbs b/ui/packages/consul-ui/app/templates/dc/acls/tokens/edit.hbs index 111a1f3452..e1f4c79292 100644 --- a/ui/packages/consul-ui/app/templates/dc/acls/tokens/edit.hbs +++ b/ui/packages/consul-ui/app/templates/dc/acls/tokens/edit.hbs @@ -91,11 +91,18 @@ as |dc partition nspace item create|}}
AccessorID
- {{item.AccessorID}} +
Token
- {{item.SecretID}} +
{{#if (and (not (token/is-legacy item)) (not create))}}
Scope
diff --git a/ui/packages/consul-ui/app/templates/dc/peers/index.hbs b/ui/packages/consul-ui/app/templates/dc/peers/index.hbs deleted file mode 100644 index 9b040c12fe..0000000000 --- a/ui/packages/consul-ui/app/templates/dc/peers/index.hbs +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - -{{#let - - (hash - value=(or sortBy "Name:asc") - change=(action (mut sortBy) value="target.selected") - ) - - (hash - searchproperty=(hash - value=(if (not-eq searchproperty undefined) - (split searchproperty ',') - searchProperties - ) - change=(action (mut searchproperty) value="target.selectedItems") - default=searchProperties - ) - ) - - loader.data - -as |sort filters items|}} - - -

- -

-
- - {{#if (gt items.length 0)}} - - {{/if}} - - - - - - - - -

{{item.Name}}

-
- -
- - -
- {{t 'routes.dc.peers.index.detail.imported.count' - count=(format-number item.ImportedServiceCount) - }} -
- -
- {{t 'routes.dc.peers.index.detail.exported.count' - count=(format-number item.ExportedServiceCount) - }} -
- -
-
- - {{#if (can 'delete peer' item=item)}} - - - {{#if true}} - - - View - - - {{/if}} - - {{/if}} - -
- -
- - {{!-- TODO: do we need to check permissions here or will we receive an error automatically? --}} - - -

- {{#if (gt items.length 0)}} - No peers found - {{else}} - Welcome to Peers - {{/if}} -

-
- - {{#if (gt items.length 0)}} - No peers where found matching that search, or you may not have access to view the peers you are searching for. - {{else}} - Peering allows an admin partition in one datacenter to communicate with a partition in a different - datacenter. There don't seem to be any peers for this admin partition, or you may not have - peering:read permissions to - access this view. - {{/if}} - - - - - -
-
-
-
- -
-{{/let}} -
-
-
diff --git a/ui/packages/consul-ui/app/utils/get-environment.js b/ui/packages/consul-ui/app/utils/get-environment.js index 157eef2f8e..fd3757fbff 100644 --- a/ui/packages/consul-ui/app/utils/get-environment.js +++ b/ui/packages/consul-ui/app/utils/get-environment.js @@ -124,13 +124,17 @@ export default function(config = {}, win = window, doc = document) { return typeof operatorConfig.PartitionsEnabled === 'undefined' ? false : operatorConfig.PartitionsEnabled; + case 'CONSUL_PEERINGS_ENABLED': + return typeof operatorConfig.PeeringEnabled === 'undefined' + ? false + : operatorConfig.PeeringEnabled; case 'CONSUL_DATACENTER_LOCAL': return operatorConfig.LocalDatacenter; case 'CONSUL_DATACENTER_PRIMARY': return operatorConfig.PrimaryDatacenter; case 'CONSUL_UI_CONFIG': dashboards = { - service: undefined + service: undefined, }; provider = env('CONSUL_METRICS_PROVIDER'); proxy = env('CONSUL_METRICS_PROXY_ENABLED'); @@ -209,6 +213,9 @@ export default function(config = {}, win = window, doc = document) { case 'CONSUL_METRICS_PROXY_ENABLE': prev['CONSUL_METRICS_PROXY_ENABLED'] = !!JSON.parse(String(value).toLowerCase()); break; + case 'CONSUL_PEERINGS_ENABLE': + prev['CONSUL_PEERINGS_ENABLED'] = !!JSON.parse(String(value).toLowerCase()); + break; case 'CONSUL_UI_CONFIG': prev['CONSUL_UI_CONFIG'] = JSON.parse(value); break; @@ -241,6 +248,7 @@ export default function(config = {}, win = window, doc = document) { case 'CONSUL_DATACENTER_PRIMARY': case 'CONSUL_ACLS_ENABLED': case 'CONSUL_NSPACES_ENABLED': + case 'CONSUL_PEERINGS_ENABLED': case 'CONSUL_SSO_ENABLED': case 'CONSUL_PARTITIONS_ENABLED': case 'CONSUL_METRICS_PROVIDER': diff --git a/ui/packages/consul-ui/config/environment.js b/ui/packages/consul-ui/config/environment.js index f62c13efcd..a85b0093d8 100644 --- a/ui/packages/consul-ui/config/environment.js +++ b/ui/packages/consul-ui/config/environment.js @@ -82,6 +82,7 @@ module.exports = function(environment, $ = process.env) { ACLsEnabled: false, NamespacesEnabled: false, SSOEnabled: false, + PeeringEnabled: false, PartitionsEnabled: false, LocalDatacenter: env('CONSUL_DATACENTER_LOCAL', 'dc1'), PrimaryDatacenter: env('CONSUL_DATACENTER_PRIMARY', 'dc1'), @@ -105,15 +106,13 @@ module.exports = function(environment, $ = process.env) { ACLsEnabled: env('CONSUL_ACLS_ENABLED', true), NamespacesEnabled: env('CONSUL_NSPACES_ENABLED', false), SSOEnabled: env('CONSUL_SSO_ENABLED', false), + // in testing peering feature is on by default + PeeringEnabled: env('CONSUL_PEERINGS_ENABLED', true), PartitionsEnabled: env('CONSUL_PARTITIONS_ENABLED', false), LocalDatacenter: env('CONSUL_DATACENTER_LOCAL', 'dc1'), PrimaryDatacenter: env('CONSUL_DATACENTER_PRIMARY', 'dc1'), }, - features: { - peering: true, - }, - '@hashicorp/ember-cli-api-double': { 'auto-import': false, enabled: true, @@ -134,15 +133,13 @@ module.exports = function(environment, $ = process.env) { autoboot: false, }), }); + break; case environment === 'development': ENV = Object.assign({}, ENV, { torii: { disableRedirectInitializer: true, }, - features: { - peering: true, - }, }); break; case environment === 'staging': @@ -161,6 +158,7 @@ module.exports = function(environment, $ = process.env) { ACLsEnabled: env('CONSUL_ACLS_ENABLED', true), NamespacesEnabled: env('CONSUL_NSPACES_ENABLED', true), SSOEnabled: env('CONSUL_SSO_ENABLED', true), + PeeringEnabled: env('CONSUL_PEERINGS_ENABLED', true), PartitionsEnabled: env('CONSUL_PARTITIONS_ENABLED', true), LocalDatacenter: env('CONSUL_DATACENTER_LOCAL', 'dc1'), PrimaryDatacenter: env('CONSUL_DATACENTER_PRIMARY', 'dc1'), diff --git a/ui/packages/consul-ui/docs/bookmarklets.mdx b/ui/packages/consul-ui/docs/bookmarklets.mdx index cc19f72171..0854dc6331 100644 --- a/ui/packages/consul-ui/docs/bookmarklets.mdx +++ b/ui/packages/consul-ui/docs/bookmarklets.mdx @@ -12,6 +12,7 @@ Below is a list of the most commonly used functions as bookmarklets followed by | [Enable ACLs](javascript:Scenario('CONSUL_ACLS_ENABLE=1')) | Enable ACLs | | [Enable TProxy](javascript:Scenario('CONSUL_TPROXY_ENABLE=1')) | Enable TProxy | | [Enable Nspaces](javascript:Scenario('CONSUL_NSPACES_ENABLE=1')) | Enable Namespace Support | +| [Enable Peers](javascript:Scenario('CONSUL_PEERINGS_ENABLE=1')) | Enable Peering Support | | [Enable Partitions](javascript:Scenario('CONSUL_PARTITIONS_ENABLE=1')) | Enable Admin Partition Support | | [Enable SSO](javascript:Scenario('CONSUL_SSO_ENABLE=1')) | Enable SSO Support | | [Enable Metrics](javascript:Scenario('CONSUL_METRICS_PROXY_ENABLE=1;CONSUL_METRICS_PROVIDER=prometheus')) | Enable all configuration required for viewing the full Metrics Visualization | diff --git a/ui/packages/consul-ui/ember-cli-build.js b/ui/packages/consul-ui/ember-cli-build.js index 8f2a92e152..576ea55ee9 100644 --- a/ui/packages/consul-ui/ember-cli-build.js +++ b/ui/packages/consul-ui/ember-cli-build.js @@ -30,6 +30,7 @@ module.exports = function(defaults, $ = process.env) { 'consul-ui', 'consul-acls', 'consul-lock-sessions', + 'consul-peerings', 'consul-partitions', 'consul-nspaces', 'consul-hcp' diff --git a/ui/packages/consul-ui/lib/startup/templates/body.html.js b/ui/packages/consul-ui/lib/startup/templates/body.html.js index 0722a60d6a..b4c46266ee 100644 --- a/ui/packages/consul-ui/lib/startup/templates/body.html.js +++ b/ui/packages/consul-ui/lib/startup/templates/body.html.js @@ -59,6 +59,10 @@ ${ {{if .ACLsEnabled}} {{end}} +{{if .PeeringEnabled}} + + +{{end}} {{if .PartitionsEnabled}} @@ -87,6 +91,7 @@ ${ key => document.cookie.split('; ').find(item => item.startsWith(\`\${key}=\`)), { 'CONSUL_ACLS_ENABLE': 'consul-acls', + 'CONSUL_PEERINGS_ENABLE': 'consul-peerings', 'CONSUL_PARTITIONS_ENABLE': 'consul-partitions', 'CONSUL_NSPACES_ENABLE': 'consul-nspaces', 'CONSUL_HCP_ENABLE': 'consul-hcp' diff --git a/ui/packages/consul-ui/node-tests/config/environment.js b/ui/packages/consul-ui/node-tests/config/environment.js index 0a88fa02a7..fc64faf944 100644 --- a/ui/packages/consul-ui/node-tests/config/environment.js +++ b/ui/packages/consul-ui/node-tests/config/environment.js @@ -21,6 +21,7 @@ test( NamespacesEnabled: false, SSOEnabled: false, PartitionsEnabled: false, + PeeringEnabled: true, LocalDatacenter: 'dc1', PrimaryDatacenter: 'dc1', } @@ -36,6 +37,7 @@ test( NamespacesEnabled: true, SSOEnabled: false, PartitionsEnabled: false, + PeeringEnabled: true, LocalDatacenter: 'dc1', PrimaryDatacenter: 'dc1', } @@ -51,6 +53,7 @@ test( NamespacesEnabled: false, SSOEnabled: true, PartitionsEnabled: false, + PeeringEnabled: true, LocalDatacenter: 'dc1', PrimaryDatacenter: 'dc1', } @@ -63,6 +66,7 @@ test( NamespacesEnabled: true, SSOEnabled: true, PartitionsEnabled: true, + PeeringEnabled: true, LocalDatacenter: 'dc1', PrimaryDatacenter: 'dc1', } diff --git a/ui/packages/consul-ui/package.json b/ui/packages/consul-ui/package.json index e40b6fe280..e03887cab5 100644 --- a/ui/packages/consul-ui/package.json +++ b/ui/packages/consul-ui/package.json @@ -82,6 +82,7 @@ "consul-hcp": "*", "consul-lock-sessions": "*", "consul-nspaces": "*", + "consul-peerings": "*", "consul-partitions": "*", "css.escape": "^1.5.1", "d3-array": "^2.8.0", diff --git a/ui/packages/consul-ui/tests/integration/components/secret-button-test.js b/ui/packages/consul-ui/tests/integration/components/secret-button-test.js deleted file mode 100644 index b0f0ee13b0..0000000000 --- a/ui/packages/consul-ui/tests/integration/components/secret-button-test.js +++ /dev/null @@ -1,33 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { render, find } from '@ember/test-helpers'; -import hbs from 'htmlbars-inline-precompile'; - -module('Integration | Component | secret button', function(hooks) { - setupRenderingTest(hooks); - - test('it renders', async function(assert) { - // Set any properties with this.set('myProperty', 'value'); - // Handle any actions with this.on('myAction', function(val) { ... }); - - await render(hbs`{{secret-button}}`); - - assert.ok( - find('*') - .textContent.trim() - .indexOf('Reveal') !== -1 - ); - - // Template block usage: - await render(hbs` - {{#secret-button}} - {{/secret-button}} - `); - - assert.ok( - find('*') - .textContent.trim() - .indexOf('Reveal') !== -1 - ); - }); -}); diff --git a/ui/packages/consul-ui/translations/components/consul/en-us.yaml b/ui/packages/consul-ui/translations/components/consul/en-us.yaml index 48975d53d2..0809332f43 100644 --- a/ui/packages/consul-ui/translations/components/consul/en-us.yaml +++ b/ui/packages/consul-ui/translations/components/consul/en-us.yaml @@ -1,3 +1,19 @@ +peer: + search-bar: + state: + name: Status + options: + pending: Pending + establishing: Establishing + active: Active + failing: Failing + terminated: Terminated + deleting: Deleting + sort: + state: + name: Status + asc: Pending to Deleting + desc: Deleting to Pending service: search-bar: kind: Service Type diff --git a/ui/packages/consul-ui/vendor/consul-ui/routes.js b/ui/packages/consul-ui/vendor/consul-ui/routes.js index b8b20c60b6..12552d42e8 100644 --- a/ui/packages/consul-ui/vendor/consul-ui/routes.js +++ b/ui/packages/consul-ui/vendor/consul-ui/routes.js @@ -34,24 +34,6 @@ }, }, }, - peers: { - _options: { path: '/peers' }, - index: { - _options: { - path: '/', - }, - }, - edit: { - _options: { - path: '/:name' - }, - addresses: { - _options: { - path: '/addresses', - }, - }, - }, - }, services: { _options: { path: '/services' }, index: { diff --git a/ui/packages/consul-ui/vendor/consul-ui/services.js b/ui/packages/consul-ui/vendor/consul-ui/services.js index ff679e2d28..13f2f054b3 100644 --- a/ui/packages/consul-ui/vendor/consul-ui/services.js +++ b/ui/packages/consul-ui/vendor/consul-ui/services.js @@ -15,6 +15,9 @@ 'component:consul/partition/selector': { class: '@glimmer/component', }, + 'component:consul/peer/selector': { + class: '@glimmer/component', + }, }))( ( json, diff --git a/website/content/commands/config/delete.mdx b/website/content/commands/config/delete.mdx index bee9667004..048832dda2 100644 --- a/website/content/commands/config/delete.mdx +++ b/website/content/commands/config/delete.mdx @@ -56,6 +56,8 @@ Usage: `consul config delete [options]` `proxy-defaults` config entry must be `global`, and the name of the `mesh` config entry must be `mesh`. +- `-filename` - Specifies the file describing the config entry to delete. + - `-cas` - Perform a Check-And-Set operation. Specifying this value also requires the -modify-index flag to be set. The default value is false. @@ -67,3 +69,5 @@ Usage: `consul config delete [options]` $ consul config delete -kind service-defaults -name web $ consul config delete -kind service-defaults -name web -cas -modify-index 26 + + $ consul config delete -filename service-defaults-web.hcl diff --git a/website/content/docs/connect/cluster-peering/create-manage-peering.mdx b/website/content/docs/connect/cluster-peering/create-manage-peering.mdx index 7fde8293b6..72b872151d 100644 --- a/website/content/docs/connect/cluster-peering/create-manage-peering.mdx +++ b/website/content/docs/connect/cluster-peering/create-manage-peering.mdx @@ -47,15 +47,13 @@ Create a JSON file that contains the first cluster's name and the peering token. ## Establish a connection between clusters -Next, use the peering token to establish a secure connection between the clusters. In the client agents of "cluster-02," establish the peering connection using the HTTP API. This endpoint does not generate an output unless there is an error. +Next, use `peering_token.json` to establish a secure connection between the clusters. In the client agents of "cluster-02," establish the peering connection using the HTTP API. This endpoint does not generate an output unless there is an error. ```shell-session $ curl --request POST --data @peering_token.json http://127.0.0.1:8500/v1/peering/establish ``` -In the peer parameter, specify a name for the first cluster. The `PeeringToken` parameter should include the entire peering token created in the first cluster. - -When you connect server agents through cluster peering, they will peer their default partitions. To establish peering connections for other partitions through server agents, you must specify the partitions you want to peer using the `Partition` field of the request body. +When you connect server agents through cluster peering, they peer their default partitions. To establish peering connections for other partitions through server agents, you must add the `Partition` field to `peering_token.json` and specify the partitions you want to peer. For additional configuration information, refer to [Cluster Peering - HTTP API](/api-docs/peering). ## Export service endpoints @@ -131,7 +129,7 @@ To confirm that you peered your clusters, you can [query the `/health/service` e ```shell-session $ curl \ - "http://127.0.0.1:8500/v1/health/service/service-name?peer=cluster-01" + "http://127.0.0.1:8500/v1/health/service/?peer=cluster-01" ``` A successful query will include service information in the output. diff --git a/website/content/docs/discovery/dns.mdx b/website/content/docs/discovery/dns.mdx index 17c25e6e61..471b9f9a20 100644 --- a/website/content/docs/discovery/dns.mdx +++ b/website/content/docs/discovery/dns.mdx @@ -376,12 +376,14 @@ If you need more complex behavior, please use the To find the unique virtual IP allocated for a service: ```text -.virtual. +.virtual[.peer]. ``` This will return the unique virtual IP for any [Connect-capable](/docs/connect) service. Each Connect service has a virtual IP assigned to it by Consul - this is used by sidecar proxies for the [Transparent Proxy](/docs/connect/transparent-proxy) feature. +The peer name is an optional part of the FQDN, and it is used to query for the virtual IP +of a service imported from that peer. The virtual IP is also added to the service's [Tagged Addresses](/docs/discovery/services#tagged-addresses) under the `consul-virtual` tag. diff --git a/website/content/docs/ecs/compatibility.mdx b/website/content/docs/ecs/compatibility.mdx new file mode 100644 index 0000000000..3967b4b51b --- /dev/null +++ b/website/content/docs/ecs/compatibility.mdx @@ -0,0 +1,22 @@ +--- +layout: docs +page_title: Compatibility Matrix +description: Compatibility Matrix for Consul ECS +--- + +# Compatibility Matrix for Consul on ECS + +For every release of Consul on ECS, the `consul-ecs` binary and `consul-ecs` Terraform module are updated. The versions of the Terraform module and binary are tightly coupled. For example, `consul-ecs` 0.4.1 binary must use the `consul-ecs` 0.4.1 Terraform module. + +## Supported Consul versions + +| Consul Version | Compatible consul-ecs Versions | +| -------------- | ------------------------------- | +| 1.12.x | 0.5.x | +| 1.11.x | 0.3.0, 0.4.x | +| 1.10.x | 0.2.x | + + +## Supported Envoy versions + +Refer to [Envoy - Supported Versions](/docs/connect/proxies/envoy#supported-versions) for information about which versions of Envoy are supported for each version of Consul. As a best practice, we recommend using the default version of Envoy that is provided in the Terraform module. This is because we test the default versions with Consul ECS binaries for the given version. diff --git a/website/content/docs/ecs/enterprise.mdx b/website/content/docs/ecs/enterprise.mdx index 9350fc6dbf..29bd1a3152 100644 --- a/website/content/docs/ecs/enterprise.mdx +++ b/website/content/docs/ecs/enterprise.mdx @@ -84,7 +84,7 @@ is not provided when `consul_partitions_enabled = true`, will default to the `de ```hcl module "acl_controller" { - source = "hashicorp/consul/aws//modules/acl-controller" + source = "hashicorp/consul-ecs/aws//modules/acl-controller" ... @@ -109,7 +109,7 @@ The following example demonstrates how to create a `mesh-task` assigned to the a ```hcl module "my_task" { - source = "hashicorp/consul/aws//modules/mesh-task" + source = "hashicorp/consul-ecs/aws//modules/mesh-task" family = "my_task" ... diff --git a/website/content/docs/ecs/terraform/migrate-existing-tasks.mdx b/website/content/docs/ecs/terraform/migrate-existing-tasks.mdx index 574e1fda0d..fa39683f90 100644 --- a/website/content/docs/ecs/terraform/migrate-existing-tasks.mdx +++ b/website/content/docs/ecs/terraform/migrate-existing-tasks.mdx @@ -68,7 +68,7 @@ The `mesh-task` module is used as follows: ```hcl module "my_task" { - source = "hashicorp/consul/aws//modules/mesh-task" + source = "hashicorp/consul-ecs/aws//modules/mesh-task" version = "" family = "my_task" diff --git a/website/content/docs/ecs/terraform/secure-configuration.mdx b/website/content/docs/ecs/terraform/secure-configuration.mdx index 24e3e165cf..81e508d445 100644 --- a/website/content/docs/ecs/terraform/secure-configuration.mdx +++ b/website/content/docs/ecs/terraform/secure-configuration.mdx @@ -80,7 +80,7 @@ the AWS IAM auth method. ```hcl module "acl_controller" { - source = "hashicorp/consul/aws//modules/acl-controller" + source = "hashicorp/consul-ecs/aws//modules/acl-controller" version = "" consul_bootstrap_token_secret_arn = aws_secretsmanager_secret.bootstrap_token.arn @@ -141,7 +141,7 @@ should be the same as the `name_prefix` you provide to the ACL controller module ```hcl module "my_task" { - source = "hashicorp/consul/aws//modules/mesh-task" + source = "hashicorp/consul-ecs/aws//modules/mesh-task" version = "" ... diff --git a/website/content/docs/nia/enterprise/index.mdx b/website/content/docs/nia/enterprise/index.mdx index d5349cca27..38f8260f21 100644 --- a/website/content/docs/nia/enterprise/index.mdx +++ b/website/content/docs/nia/enterprise/index.mdx @@ -25,3 +25,6 @@ Enterprise features of CTS address organization complexities of collaboration, o | Governance | | [Sentinel](https://www.terraform.io/docs/cloud/sentinel/index.html) to enforce governance policies as code | The [Terraform Cloud driver](/docs/nia/configuration#terraform-cloud-driver) enables CTS Enterprise to integrate with Terraform Cloud or Terraform Enterprise. The [Terraform Cloud driver](/docs/nia/network-drivers/terraform-cloud) page provides an overview of how the integration works within CTS. + +## Consul Admin Partition Support +CTS subscribes to a Consul agent. Depending on the admin partition the Consul agent is a part of and the services within the admin partition, CTS will be able to subscribe to those services and support the automation workflow. As such, admin partitions are not relevant to the CTS workflow. We recommend deploying a single CTS instance that subscribes to services/KV within a single partition and using a different CTS instance (or instances) to subscribe to services/KV in another partition. diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 56d4a739a1..27b468c41a 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -787,6 +787,10 @@ { "title": "Configuration Reference", "path": "ecs/configuration-reference" + }, + { + "title": "Compatibility Matrix", + "path": "ecs/compatibility" } ] },