agent: update proxy upstreams to inherit namespace from service (#10688)

(cherry picked from commit 91c90a672a)
This commit is contained in:
Chris S. Kim 2021-07-26 17:12:29 -04:00 committed by kisunji
parent 2442074ffb
commit 45232780cd
7 changed files with 61 additions and 26 deletions

3
.changelog/10688.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
connect: proxy upstreams inherit namespace from service if none are defined.
```

View File

@ -18,6 +18,12 @@ import (
"testing"
"time"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/serf/serf"
"github.com/mitchellh/hashstructure"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/config"
"github.com/hashicorp/consul/agent/connect"
@ -34,10 +40,6 @@ import (
"github.com/hashicorp/consul/sdk/testutil/retry"
"github.com/hashicorp/consul/testrpc"
"github.com/hashicorp/consul/types"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/serf/serf"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func makeReadOnlyAgentACL(t *testing.T, srv *HTTPHandlers) string {
@ -353,15 +355,14 @@ func TestAgent_Service(t *testing.T) {
// API struct types.
expectProxy := proxy
expectProxy.Upstreams =
structs.TestAddDefaultsToUpstreams(t, sidecarProxy.Proxy.Upstreams)
structs.TestAddDefaultsToUpstreams(t, sidecarProxy.Proxy.Upstreams, *structs.DefaultEnterpriseMeta())
expectedResponse := &api.AgentService{
Kind: api.ServiceKindConnectProxy,
ID: "web-sidecar-proxy",
Service: "web-sidecar-proxy",
Port: 8000,
Proxy: expectProxy.ToAPI(),
ContentHash: "4c7d5f8d3748be6d",
Kind: api.ServiceKindConnectProxy,
ID: "web-sidecar-proxy",
Service: "web-sidecar-proxy",
Port: 8000,
Proxy: expectProxy.ToAPI(),
Weights: api.AgentWeights{
Passing: 1,
Warning: 1,
@ -371,11 +372,21 @@ func TestAgent_Service(t *testing.T) {
Datacenter: "dc1",
}
fillAgentServiceEnterpriseMeta(expectedResponse, structs.DefaultEnterpriseMeta())
hash1, err := hashstructure.Hash(expectedResponse, nil)
if err != nil {
t.Fatalf("error generating hash: %v", err)
}
expectedResponse.ContentHash = fmt.Sprintf("%x", hash1)
// Copy and modify
updatedResponse := *expectedResponse
updatedResponse.Port = 9999
updatedResponse.ContentHash = "713435ba1f5badcf"
updatedResponse.ContentHash = "" // clear field before generating a new hash
hash2, err := hashstructure.Hash(updatedResponse, nil)
if err != nil {
t.Fatalf("error generating hash: %v", err)
}
updatedResponse.ContentHash = fmt.Sprintf("%x", hash2)
// Simple response for non-proxy service registered in TestAgent config
expectWebResponse := &api.AgentService{
@ -3293,8 +3304,18 @@ func testAgent_RegisterService_UnmanagedConnectProxy(t *testing.T, extraHCL stri
svc := a.State.Service(sid)
require.NotNil(t, svc, "has service")
require.Equal(t, structs.ServiceKindConnectProxy, svc.Kind)
// Registration must set that default type
args.Proxy.Upstreams[0].DestinationType = api.UpstreamDestTypeService
// Registration sets default types and namespaces
for i := range args.Proxy.Upstreams {
if args.Proxy.Upstreams[i].DestinationType == "" {
args.Proxy.Upstreams[i].DestinationType = api.UpstreamDestTypeService
}
if args.Proxy.Upstreams[i].DestinationNamespace == "" {
args.Proxy.Upstreams[i].DestinationNamespace =
structs.DefaultEnterpriseMeta().NamespaceOrEmpty()
}
}
require.Equal(t, args.Proxy, svc.Proxy.ToAPI())
// Ensure the token was configured

View File

@ -6961,9 +6961,10 @@ func TestFullConfig(t *testing.T) {
},
Upstreams: structs.Upstreams{
{
DestinationType: "service", // Default should be explicitly filled
DestinationName: "KPtAj2cb",
LocalBindPort: 4051,
DestinationType: "service", // Default should be explicitly filled
DestinationName: "KPtAj2cb",
DestinationNamespace: defaultEntMeta.NamespaceOrEmpty(),
LocalBindPort: 4051,
Config: map[string]interface{}{
"kzRnZOyd": "nUNKoL8H",
},

View File

@ -18,7 +18,7 @@ func (a *Agent) sidecarServiceID(serviceID string) string {
// config.
//
// It assumes the ns has been validated already which means the nested
// SidecarService is also already validated.It also assumes that any check
// SidecarService is also already validated. It also assumes that any check
// definitions within the sidecar service definition have been validated if
// necessary. If no sidecar service is defined in ns, then nil is returned with
// nil error.
@ -34,6 +34,9 @@ func (a *Agent) sidecarServiceFromNodeService(ns *structs.NodeService, token str
return nil, nil, "", nil
}
// for now at least these must be identical
ns.Connect.SidecarService.EnterpriseMeta = ns.EnterpriseMeta
// Start with normal conversion from service definition
sidecar := ns.Connect.SidecarService.NodeService()
@ -41,9 +44,6 @@ func (a *Agent) sidecarServiceFromNodeService(ns *structs.NodeService, token str
// ID. We rely on this for lifecycle management of the nested definition.
sidecar.ID = a.sidecarServiceID(ns.ID)
// for now at least these must be identical
sidecar.EnterpriseMeta = ns.EnterpriseMeta
// Set some meta we can use to disambiguate between service instances we added
// later and are responsible for deregistering.
if sidecar.Meta != nil {

View File

@ -124,7 +124,8 @@ func TestAgent_sidecarServiceFromNodeService(t *testing.T) {
LocalServiceAddress: "127.0.127.0",
LocalServicePort: 9999,
Config: map[string]interface{}{"baz": "qux"},
Upstreams: structs.TestAddDefaultsToUpstreams(t, structs.TestUpstreams(t)),
Upstreams: structs.TestAddDefaultsToUpstreams(t, structs.TestUpstreams(t),
*structs.DefaultEnterpriseMeta()),
},
},
wantChecks: []*structs.CheckType{
@ -303,7 +304,7 @@ func TestAgent_sidecarServiceFromNodeService(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Set port range to be tiny (one availabl) to test consuming all of it.
// Set port range to be tiny (one available) to test consuming all of it.
// This allows a single assigned port at 2222 thanks to being inclusive at
// both ends.
if tt.maxPort == 0 {

View File

@ -78,11 +78,17 @@ func (s *ServiceDefinition) NodeService() *NodeService {
}
if s.Proxy != nil {
ns.Proxy = *s.Proxy
// Ensure the Upstream type is defaulted
for i := range ns.Proxy.Upstreams {
// Ensure the Upstream type is defaulted
if ns.Proxy.Upstreams[i].DestinationType == "" {
ns.Proxy.Upstreams[i].DestinationType = UpstreamDestTypeService
}
// If a proxy's namespace is not defined, inherit the server's namespace.
// Applicable only to Consul Enterprise.
if ns.Proxy.Upstreams[i].DestinationNamespace == "" {
ns.Proxy.Upstreams[i].DestinationNamespace = ns.EnterpriseMeta.NamespaceOrEmpty()
}
}
ns.Proxy.Expose = s.Proxy.Expose
}

View File

@ -37,9 +37,9 @@ func TestUpstreams(t testing.T) Upstreams {
// TestAddDefaultsToUpstreams takes an array of upstreams (such as that from
// TestUpstreams) and adds default values that are populated during
// refigistration. Use this for generating the expected Upstreams value after
// registration. Use this for generating the expected Upstreams value after
// registration.
func TestAddDefaultsToUpstreams(t testing.T, upstreams []Upstream) Upstreams {
func TestAddDefaultsToUpstreams(t testing.T, upstreams []Upstream, entMeta EnterpriseMeta) Upstreams {
ups := make([]Upstream, len(upstreams))
for i := range upstreams {
ups[i] = upstreams[i]
@ -47,6 +47,9 @@ func TestAddDefaultsToUpstreams(t testing.T, upstreams []Upstream) Upstreams {
if ups[i].DestinationType == "" {
ups[i].DestinationType = UpstreamDestTypeService
}
if ups[i].DestinationNamespace == "" {
ups[i].DestinationNamespace = entMeta.NamespaceOrEmpty()
}
}
return ups
}