92fe8c8e89
* Refactor Service Definition ProxyDestination. This includes: - Refactoring all internal structs used - Updated tests for both deprecated and new input for: - Agent Services endpoint response - Agent Service endpoint response - Agent Register endpoint - Unmanaged deprecated field - Unmanaged new fields - Managed deprecated upstreams - Managed new - Catalog Register - Unmanaged deprecated field - Unmanaged new fields - Managed deprecated upstreams - Managed new - Catalog Services endpoint response - Catalog Node endpoint response - Catalog Service endpoint response - Updated API tests for all of the above too (both deprecated and new forms of register) TODO: - config package changes for on-disk service definitions - proxy config endpoint - built-in proxy support for new fields * Agent proxy config endpoint updated with upstreams * Config file changes for upstreams. * Add upstream opaque config and update all tests to ensure it works everywhere. * Built in proxy working with new Upstreams config * Command fixes and deprecations * Fix key translation, upstream type defaults and a spate of other subtele bugs found with ned to end test scripts... TODO: tests still failing on one case that needs a fix. I think it's key translation for upstreams nested in Managed proxy struct. * Fix translated keys in API registration. ≈ * Fixes from docs - omit some empty undocumented fields in API - Bring back ServiceProxyDestination in Catalog responses to not break backwards compat - this was removed assuming it was only used internally. * Documentation updates for Upstreams in service definition * Fixes for tests broken by many refactors. * Enable travis on f-connect branch in this branch too. * Add consistent Deprecation comments to ProxyDestination uses * Update version number on deprecation notices, and correct upstream datacenter field with explanation in docs
328 lines
7.3 KiB
Go
328 lines
7.3 KiB
Go
package connect
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/consul/agent"
|
|
"github.com/hashicorp/consul/agent/connect"
|
|
"github.com/hashicorp/consul/api"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestStaticResolver_Resolve(t *testing.T) {
|
|
type fields struct {
|
|
Addr string
|
|
CertURI connect.CertURI
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
}{
|
|
{
|
|
name: "simples",
|
|
fields: fields{"1.2.3.4:80", connect.TestSpiffeIDService(t, "foo")},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
sr := StaticResolver{
|
|
Addr: tt.fields.Addr,
|
|
CertURI: tt.fields.CertURI,
|
|
}
|
|
addr, certURI, err := sr.Resolve(context.Background())
|
|
require := require.New(t)
|
|
require.Nil(err)
|
|
require.Equal(sr.Addr, addr)
|
|
require.Equal(sr.CertURI, certURI)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConsulResolver_Resolve(t *testing.T) {
|
|
// Setup a local test agent to query
|
|
agent := agent.NewTestAgent("test-consul", "")
|
|
defer agent.Shutdown()
|
|
|
|
cfg := api.DefaultConfig()
|
|
cfg.Address = agent.HTTPAddr()
|
|
client, err := api.NewClient(cfg)
|
|
require.Nil(t, err)
|
|
|
|
// Setup a service with a connect proxy instance
|
|
regSrv := &api.AgentServiceRegistration{
|
|
Name: "web",
|
|
Port: 8080,
|
|
}
|
|
err = client.Agent().ServiceRegister(regSrv)
|
|
require.Nil(t, err)
|
|
|
|
regProxy := &api.AgentServiceRegistration{
|
|
Kind: "connect-proxy",
|
|
Name: "web-proxy",
|
|
Port: 9090,
|
|
Proxy: &api.AgentServiceConnectProxyConfig{
|
|
DestinationServiceName: "web",
|
|
},
|
|
}
|
|
err = client.Agent().ServiceRegister(regProxy)
|
|
require.Nil(t, err)
|
|
|
|
// And another proxy so we can test handling with multiple endpoints returned
|
|
regProxy.Port = 9091
|
|
regProxy.ID = "web-proxy-2"
|
|
err = client.Agent().ServiceRegister(regProxy)
|
|
require.Nil(t, err)
|
|
|
|
// Add a native service
|
|
{
|
|
regSrv := &api.AgentServiceRegistration{
|
|
Name: "db",
|
|
Port: 8080,
|
|
Connect: &api.AgentServiceConnect{
|
|
Native: true,
|
|
},
|
|
}
|
|
require.NoError(t, client.Agent().ServiceRegister(regSrv))
|
|
}
|
|
|
|
// Add a prepared query
|
|
queryId, _, err := client.PreparedQuery().Create(&api.PreparedQueryDefinition{
|
|
Name: "test-query",
|
|
Service: api.ServiceQuery{
|
|
Service: "web",
|
|
Connect: true,
|
|
},
|
|
}, nil)
|
|
require.NoError(t, err)
|
|
|
|
proxyAddrs := []string{
|
|
agent.Config.AdvertiseAddrLAN.String() + ":9090",
|
|
agent.Config.AdvertiseAddrLAN.String() + ":9091",
|
|
}
|
|
|
|
type fields struct {
|
|
Namespace string
|
|
Name string
|
|
Type int
|
|
Datacenter string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
timeout time.Duration
|
|
wantAddr string
|
|
wantCertURI connect.CertURI
|
|
wantErr bool
|
|
addrs []string
|
|
}{
|
|
{
|
|
name: "basic service discovery",
|
|
fields: fields{
|
|
Namespace: "default",
|
|
Name: "web",
|
|
Type: ConsulResolverTypeService,
|
|
},
|
|
wantCertURI: connect.TestSpiffeIDService(t, "web"),
|
|
wantErr: false,
|
|
addrs: proxyAddrs,
|
|
},
|
|
{
|
|
name: "basic service with native service",
|
|
fields: fields{
|
|
Namespace: "default",
|
|
Name: "db",
|
|
Type: ConsulResolverTypeService,
|
|
},
|
|
wantCertURI: connect.TestSpiffeIDService(t, "db"),
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "Bad Type errors",
|
|
fields: fields{
|
|
Namespace: "default",
|
|
Name: "web",
|
|
Type: 123,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "Non-existent service errors",
|
|
fields: fields{
|
|
Namespace: "default",
|
|
Name: "foo",
|
|
Type: ConsulResolverTypeService,
|
|
},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "timeout errors",
|
|
fields: fields{
|
|
Namespace: "default",
|
|
Name: "web",
|
|
Type: ConsulResolverTypeService,
|
|
},
|
|
timeout: 1 * time.Nanosecond,
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "prepared query by id",
|
|
fields: fields{
|
|
Name: queryId,
|
|
Type: ConsulResolverTypePreparedQuery,
|
|
},
|
|
wantCertURI: connect.TestSpiffeIDService(t, "web"),
|
|
wantErr: false,
|
|
addrs: proxyAddrs,
|
|
},
|
|
{
|
|
name: "prepared query by name",
|
|
fields: fields{
|
|
Name: "test-query",
|
|
Type: ConsulResolverTypePreparedQuery,
|
|
},
|
|
wantCertURI: connect.TestSpiffeIDService(t, "web"),
|
|
wantErr: false,
|
|
addrs: proxyAddrs,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
require := require.New(t)
|
|
cr := &ConsulResolver{
|
|
Client: client,
|
|
Namespace: tt.fields.Namespace,
|
|
Name: tt.fields.Name,
|
|
Type: tt.fields.Type,
|
|
Datacenter: tt.fields.Datacenter,
|
|
}
|
|
// WithCancel just to have a cancel func in scope to assign in the if
|
|
// clause.
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
if tt.timeout > 0 {
|
|
ctx, cancel = context.WithTimeout(ctx, tt.timeout)
|
|
}
|
|
defer cancel()
|
|
gotAddr, gotCertURI, err := cr.Resolve(ctx)
|
|
if tt.wantErr {
|
|
require.NotNil(err)
|
|
return
|
|
}
|
|
|
|
require.Nil(err)
|
|
require.Equal(tt.wantCertURI, gotCertURI)
|
|
if len(tt.addrs) > 0 {
|
|
require.Contains(tt.addrs, gotAddr)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConsulResolverFromAddrFunc(t *testing.T) {
|
|
// Don't need an actual instance since we don't do the service discovery but
|
|
// we do want to assert the client is pass through correctly.
|
|
client, err := api.NewClient(api.DefaultConfig())
|
|
require.NoError(t, err)
|
|
|
|
tests := []struct {
|
|
name string
|
|
addr string
|
|
want Resolver
|
|
wantErr string
|
|
}{
|
|
{
|
|
name: "service",
|
|
addr: "foo.service.consul",
|
|
want: &ConsulResolver{
|
|
Client: client,
|
|
Namespace: "default",
|
|
Name: "foo",
|
|
Type: ConsulResolverTypeService,
|
|
},
|
|
},
|
|
{
|
|
name: "query",
|
|
addr: "foo.query.consul",
|
|
want: &ConsulResolver{
|
|
Client: client,
|
|
Namespace: "default",
|
|
Name: "foo",
|
|
Type: ConsulResolverTypePreparedQuery,
|
|
},
|
|
},
|
|
{
|
|
name: "service with dc",
|
|
addr: "foo.service.dc2.consul",
|
|
want: &ConsulResolver{
|
|
Client: client,
|
|
Datacenter: "dc2",
|
|
Namespace: "default",
|
|
Name: "foo",
|
|
Type: ConsulResolverTypeService,
|
|
},
|
|
},
|
|
{
|
|
name: "query with dc",
|
|
addr: "foo.query.dc2.consul",
|
|
want: &ConsulResolver{
|
|
Client: client,
|
|
Datacenter: "dc2",
|
|
Namespace: "default",
|
|
Name: "foo",
|
|
Type: ConsulResolverTypePreparedQuery,
|
|
},
|
|
},
|
|
{
|
|
name: "invalid host:port",
|
|
addr: "%%%",
|
|
wantErr: "invalid Consul DNS domain",
|
|
},
|
|
{
|
|
name: "custom domain",
|
|
addr: "foo.service.my-consul.com",
|
|
wantErr: "invalid Consul DNS domain",
|
|
},
|
|
{
|
|
name: "unsupported query type",
|
|
addr: "foo.connect.consul",
|
|
wantErr: "unsupported Consul DNS domain",
|
|
},
|
|
{
|
|
name: "unsupported query type and datacenter",
|
|
addr: "foo.connect.dc1.consul",
|
|
wantErr: "unsupported Consul DNS domain",
|
|
},
|
|
{
|
|
name: "unsupported query type and datacenter",
|
|
addr: "foo.connect.dc1.consul",
|
|
wantErr: "unsupported Consul DNS domain",
|
|
},
|
|
{
|
|
name: "unsupported tag filter",
|
|
addr: "tag1.foo.service.consul",
|
|
wantErr: "unsupported Consul DNS domain",
|
|
},
|
|
{
|
|
name: "unsupported tag filter with DC",
|
|
addr: "tag1.foo.service.dc1.consul",
|
|
wantErr: "unsupported Consul DNS domain",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
require := require.New(t)
|
|
|
|
fn := ConsulResolverFromAddrFunc(client)
|
|
got, gotErr := fn(tt.addr)
|
|
if tt.wantErr != "" {
|
|
require.Error(gotErr)
|
|
require.Contains(gotErr.Error(), tt.wantErr)
|
|
} else {
|
|
require.NoError(gotErr)
|
|
require.Equal(tt.want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|