From 7a365fa0da7b8605962fec786fc2cade45f3885c Mon Sep 17 00:00:00 2001 From: Evan Culver Date: Wed, 8 Dec 2021 11:02:14 -0800 Subject: [PATCH] rpc: Unset partition before forwarding to remote datacenter (#11758) --- .changelog/11758.txt | 3 +++ agent/consul/rpc.go | 21 +++++++++++++++++++++ agent/structs/structs_oss.go | 4 ++++ 3 files changed, 28 insertions(+) create mode 100644 .changelog/11758.txt diff --git a/.changelog/11758.txt b/.changelog/11758.txt new file mode 100644 index 0000000000..21436d5e53 --- /dev/null +++ b/.changelog/11758.txt @@ -0,0 +1,3 @@ +```release-note:bug +rpc: unset partition before forwarding to remote datacenter +``` diff --git a/agent/consul/rpc.go b/agent/consul/rpc.go index 9a93b562e3..c8fa6846cd 100644 --- a/agent/consul/rpc.go +++ b/agent/consul/rpc.go @@ -89,6 +89,19 @@ const ( var ErrChunkingResubmit = errors.New("please resubmit call for rechunking") +// partitionUnsetter is used to describe requests values that can unset their +// EnterpriseMeta.Partition value. +type partitionUnsetter interface { + // UnsetPartition is used to strip a Partition value from the request before + // it is forwarded to a remote datacenter. By unsetting the value, the server + // that handles the request can decide which partition should be used (or do nothing). + // This ensures that servers that are Partition-enabled (pre-1.11, or non-Enterprise) + // don't inadvertently cause servers that are not Partition-enabled (<= 1.10 or non-Enterprise) + // to filter their responses by Partition. In other words, this ensures upgraded servers + // remain compatible with non-upgraded servers. + UnsetPartition() +} + func (s *Server) rpcLogger() hclog.Logger { return s.loggers.Named(logging.RPC) } @@ -655,6 +668,14 @@ func (s *Server) forwardRequestToOtherDatacenter(info structs.RPCInfo, forwardTo } } } + // In order to interoperate with servers that can interpret Partition, but + // may not handle it correctly (eg. 1.10 servers), we need to unset the value. + // Unsetting the Partition ensures that the server that handles the request + // uses its Partition, or an empty value (aka doing nothing). + // For requests that are not Partition-aware, this is a no-op. + if v, ok := info.(partitionUnsetter); ok { + v.UnsetPartition() + } return true, forwardToDC(dc) } diff --git a/agent/structs/structs_oss.go b/agent/structs/structs_oss.go index a003adc857..acc3191d28 100644 --- a/agent/structs/structs_oss.go +++ b/agent/structs/structs_oss.go @@ -47,6 +47,10 @@ func (m *EnterpriseMeta) WithWildcardNamespace() *EnterpriseMeta { return &emptyEnterpriseMeta } +func (m *EnterpriseMeta) UnsetPartition() { + // do nothing +} + // TODO(partition): stop using this func NewEnterpriseMetaInDefaultPartition(_ string) EnterpriseMeta { return emptyEnterpriseMeta