open-consul/agent/grpc-internal/resolver/resolver_test.go
Matt Keeler e909289454
Various bits of cleanup detected when using Go Workspaces (#17462)
TLDR with many modules the versions included in each diverged quite a bit. Attempting to use Go Workspaces produces a bunch of errors.

This commit:

1. Fixes envoy-library-references.sh to work again
2. Ensures we are pulling in go-control-plane@v0.11.0 everywhere (previously it was at that version in some modules and others were much older)
3. Remove one usage of golang/protobuf that caused us to have a direct dependency on it.
4. Remove deprecated usage of the Endpoint field in the grpc resolver.Target struct. The current version of grpc (v1.55.0) has removed that field and recommended replacement with URL.Opaque and calls to the Endpoint() func when needing to consume the previous field.
4. `go work init <all the paths to go.mod files>` && `go work sync`. This syncrhonized versions of dependencies from the main workspace/root module to all submodules
5. Updated .gitignore to ignore the go.work and go.work.sum files. This seems to be standard practice at the moment.
6. Update doc comments in protoc-gen-consul-rate-limit to be go fmt compatible
7. Upgraded makefile infra to perform linting, testing and go mod tidy on all modules in a flexible manner.
8. Updated linter rules to prevent usage of golang/protobuf
9. Updated a leader peering test to account for an extra colon in a grpc error message.
2023-06-05 16:08:39 -04:00

197 lines
4.6 KiB
Go

package resolver
import (
"fmt"
"net"
"net/url"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/resolver"
"google.golang.org/grpc/serviceconfig"
"github.com/hashicorp/consul/agent/metadata"
"github.com/hashicorp/consul/types"
)
func TestServerResolverBuilder(t *testing.T) {
const agentDC = "dc1"
type testcase struct {
name string
agentType string // server/client
serverType string // server/leader
requestDC string
expectLAN bool
}
run := func(t *testing.T, tc testcase) {
rs := NewServerResolverBuilder(newConfig(t, agentDC, tc.agentType))
endpoint := ""
if tc.serverType == "leader" {
endpoint = "leader.local"
} else {
endpoint = tc.serverType + "." + tc.requestDC
}
cc := &fakeClientConn{}
_, err := rs.Build(resolver.Target{
Scheme: "consul",
Authority: rs.Authority(),
URL: url.URL{Opaque: endpoint},
}, cc, resolver.BuildOptions{})
require.NoError(t, err)
for i := 0; i < 3; i++ {
dc := fmt.Sprintf("dc%d", i+1)
for j := 0; j < 3; j++ {
wanIP := fmt.Sprintf("127.1.%d.%d", i+1, j+10)
name := fmt.Sprintf("%s-server-%d", dc, j+1)
wanMeta := newServerMeta(name, dc, wanIP, true)
if tc.agentType == "server" {
rs.AddServer(types.AreaWAN, wanMeta)
}
if dc == agentDC {
// register LAN/WAN pairs for the same instances
lanIP := fmt.Sprintf("127.0.%d.%d", i+1, j+10)
lanMeta := newServerMeta(name, dc, lanIP, false)
rs.AddServer(types.AreaLAN, lanMeta)
if j == 0 {
rs.UpdateLeaderAddr(dc, lanIP)
}
}
}
}
if tc.serverType == "leader" {
assert.Len(t, cc.state.Addresses, 1)
} else {
assert.Len(t, cc.state.Addresses, 3)
}
for _, addr := range cc.state.Addresses {
addrPrefix := tc.requestDC + "-"
if tc.expectLAN {
addrPrefix += "127.0."
} else {
addrPrefix += "127.1."
}
assert.True(t, strings.HasPrefix(addr.Addr, addrPrefix),
"%q does not start with %q (returned WAN for LAN request)", addr.Addr, addrPrefix)
if tc.expectLAN {
assert.False(t, strings.Contains(addr.ServerName, ".dc"),
"%q ends with datacenter suffix (returned WAN for LAN request)", addr.ServerName)
} else {
assert.True(t, strings.HasSuffix(addr.ServerName, "."+tc.requestDC),
"%q does not end with %q", addr.ServerName, "."+tc.requestDC)
}
}
}
cases := []testcase{
{
name: "server requesting local servers",
agentType: "server",
serverType: "server",
requestDC: agentDC,
expectLAN: true,
},
{
name: "server requesting remote servers in dc2",
agentType: "server",
serverType: "server",
requestDC: "dc2",
expectLAN: false,
},
{
name: "server requesting remote servers in dc3",
agentType: "server",
serverType: "server",
requestDC: "dc3",
expectLAN: false,
},
// ---------------
{
name: "server requesting local leader",
agentType: "server",
serverType: "leader",
requestDC: agentDC,
expectLAN: true,
},
// ---------------
{
name: "client requesting local server",
agentType: "client",
serverType: "server",
requestDC: agentDC,
expectLAN: true,
},
{
name: "client requesting local leader",
agentType: "client",
serverType: "leader",
requestDC: agentDC,
expectLAN: true,
},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
run(t, tc)
})
}
}
func newServerMeta(name, dc, ip string, wan bool) *metadata.Server {
fullname := name
if wan {
fullname = name + "." + dc
}
return &metadata.Server{
ID: name,
Name: fullname,
ShortName: name,
Datacenter: dc,
Addr: &net.IPAddr{IP: net.ParseIP(ip)},
UseTLS: false,
}
}
func newConfig(t *testing.T, dc, agentType string) Config {
n := t.Name()
s := strings.Replace(n, "/", "", -1)
s = strings.Replace(s, "_", "", -1)
return Config{
Datacenter: dc,
AgentType: agentType,
Authority: strings.ToLower(s),
}
}
// fakeClientConn implements resolver.ClientConn for tests
type fakeClientConn struct {
state resolver.State
}
var _ resolver.ClientConn = (*fakeClientConn)(nil)
func (f *fakeClientConn) UpdateState(state resolver.State) error {
f.state = state
return nil
}
func (*fakeClientConn) ReportError(error) {}
func (*fakeClientConn) NewAddress(addresses []resolver.Address) {}
func (*fakeClientConn) NewServiceConfig(serviceConfig string) {}
func (*fakeClientConn) ParseServiceConfig(serviceConfigJSON string) *serviceconfig.ParseResult {
return nil
}