command: when generating envoy bootstrap configs use the datacenter returned from the agent services endpoint (#9229)
Fixes #9215
This commit is contained in:
parent
22a0ab69ae
commit
7bcbc59dea
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:bug
|
||||||
|
command: when generating envoy bootstrap configs use the datacenter returned from the agent services endpoint
|
||||||
|
```
|
|
@ -170,7 +170,7 @@ func (s *HTTPHandlers) AgentReload(resp http.ResponseWriter, req *http.Request)
|
||||||
return nil, s.agent.ReloadConfig()
|
return nil, s.agent.ReloadConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildAgentService(s *structs.NodeService) api.AgentService {
|
func buildAgentService(s *structs.NodeService, dc string) api.AgentService {
|
||||||
weights := api.AgentWeights{Passing: 1, Warning: 1}
|
weights := api.AgentWeights{Passing: 1, Warning: 1}
|
||||||
if s.Weights != nil {
|
if s.Weights != nil {
|
||||||
if s.Weights.Passing > 0 {
|
if s.Weights.Passing > 0 {
|
||||||
|
@ -200,6 +200,7 @@ func buildAgentService(s *structs.NodeService) api.AgentService {
|
||||||
CreateIndex: s.CreateIndex,
|
CreateIndex: s.CreateIndex,
|
||||||
ModifyIndex: s.ModifyIndex,
|
ModifyIndex: s.ModifyIndex,
|
||||||
Weights: weights,
|
Weights: weights,
|
||||||
|
Datacenter: dc,
|
||||||
}
|
}
|
||||||
|
|
||||||
if as.Tags == nil {
|
if as.Tags == nil {
|
||||||
|
@ -253,9 +254,11 @@ func (s *HTTPHandlers) AgentServices(resp http.ResponseWriter, req *http.Request
|
||||||
// anyway.
|
// anyway.
|
||||||
agentSvcs := make(map[string]*api.AgentService)
|
agentSvcs := make(map[string]*api.AgentService)
|
||||||
|
|
||||||
|
dc := s.agent.config.Datacenter
|
||||||
|
|
||||||
// Use empty list instead of nil
|
// Use empty list instead of nil
|
||||||
for id, s := range services {
|
for id, s := range services {
|
||||||
agentService := buildAgentService(s)
|
agentService := buildAgentService(s, dc)
|
||||||
agentSvcs[id.ID] = &agentService
|
agentSvcs[id.ID] = &agentService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +306,8 @@ func (s *HTTPHandlers) AgentService(resp http.ResponseWriter, req *http.Request)
|
||||||
|
|
||||||
sid := structs.NewServiceID(id, &entMeta)
|
sid := structs.NewServiceID(id, &entMeta)
|
||||||
|
|
||||||
|
dc := s.agent.config.Datacenter
|
||||||
|
|
||||||
resultHash, service, err := s.agent.LocalBlockingQuery(false, hash, queryOpts.MaxQueryTime,
|
resultHash, service, err := s.agent.LocalBlockingQuery(false, hash, queryOpts.MaxQueryTime,
|
||||||
func(ws memdb.WatchSet) (string, interface{}, error) {
|
func(ws memdb.WatchSet) (string, interface{}, error) {
|
||||||
|
|
||||||
|
@ -330,7 +335,7 @@ func (s *HTTPHandlers) AgentService(resp http.ResponseWriter, req *http.Request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the content hash over the response, minus the hash field
|
// Calculate the content hash over the response, minus the hash field
|
||||||
aSvc := buildAgentService(svc)
|
aSvc := buildAgentService(svc, dc)
|
||||||
reply := &aSvc
|
reply := &aSvc
|
||||||
|
|
||||||
rawHash, err := hashstructure.Hash(reply, nil)
|
rawHash, err := hashstructure.Hash(reply, nil)
|
||||||
|
@ -768,6 +773,8 @@ func (s *HTTPHandlers) AgentHealthServiceByID(resp http.ResponseWriter, req *htt
|
||||||
|
|
||||||
sid := structs.NewServiceID(serviceID, &entMeta)
|
sid := structs.NewServiceID(serviceID, &entMeta)
|
||||||
|
|
||||||
|
dc := s.agent.config.Datacenter
|
||||||
|
|
||||||
if service := s.agent.State.Service(sid); service != nil {
|
if service := s.agent.State.Service(sid); service != nil {
|
||||||
if authz != nil && authz.ServiceRead(service.Service, &authzContext) != acl.Allow {
|
if authz != nil && authz.ServiceRead(service.Service, &authzContext) != acl.Allow {
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, acl.ErrPermissionDenied
|
||||||
|
@ -776,7 +783,7 @@ func (s *HTTPHandlers) AgentHealthServiceByID(resp http.ResponseWriter, req *htt
|
||||||
if returnTextPlain(req) {
|
if returnTextPlain(req) {
|
||||||
return status, CodeWithPayloadError{StatusCode: code, Reason: status, ContentType: "text/plain"}
|
return status, CodeWithPayloadError{StatusCode: code, Reason: status, ContentType: "text/plain"}
|
||||||
}
|
}
|
||||||
serviceInfo := buildAgentService(service)
|
serviceInfo := buildAgentService(service, dc)
|
||||||
result := &api.AgentServiceChecksInfo{
|
result := &api.AgentServiceChecksInfo{
|
||||||
AggregatedStatus: status,
|
AggregatedStatus: status,
|
||||||
Checks: healthChecks,
|
Checks: healthChecks,
|
||||||
|
@ -822,6 +829,8 @@ func (s *HTTPHandlers) AgentHealthServiceByName(resp http.ResponseWriter, req *h
|
||||||
return nil, acl.ErrPermissionDenied
|
return nil, acl.ErrPermissionDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dc := s.agent.config.Datacenter
|
||||||
|
|
||||||
code := http.StatusNotFound
|
code := http.StatusNotFound
|
||||||
status := fmt.Sprintf("ServiceName %s Not Found", serviceName)
|
status := fmt.Sprintf("ServiceName %s Not Found", serviceName)
|
||||||
services := s.agent.State.Services(&entMeta)
|
services := s.agent.State.Services(&entMeta)
|
||||||
|
@ -831,7 +840,7 @@ func (s *HTTPHandlers) AgentHealthServiceByName(resp http.ResponseWriter, req *h
|
||||||
sid := structs.NewServiceID(service.ID, &entMeta)
|
sid := structs.NewServiceID(service.ID, &entMeta)
|
||||||
|
|
||||||
scode, sstatus, healthChecks := agentHealthService(sid, s)
|
scode, sstatus, healthChecks := agentHealthService(sid, s)
|
||||||
serviceInfo := buildAgentService(service)
|
serviceInfo := buildAgentService(service, dc)
|
||||||
res := api.AgentServiceChecksInfo{
|
res := api.AgentServiceChecksInfo{
|
||||||
AggregatedStatus: sstatus,
|
AggregatedStatus: sstatus,
|
||||||
Checks: healthChecks,
|
Checks: healthChecks,
|
||||||
|
|
|
@ -365,8 +365,9 @@ func TestAgent_Service(t *testing.T) {
|
||||||
Passing: 1,
|
Passing: 1,
|
||||||
Warning: 1,
|
Warning: 1,
|
||||||
},
|
},
|
||||||
Meta: map[string]string{},
|
Meta: map[string]string{},
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
|
Datacenter: "dc1",
|
||||||
}
|
}
|
||||||
fillAgentServiceEnterpriseMeta(expectedResponse, structs.DefaultEnterpriseMeta())
|
fillAgentServiceEnterpriseMeta(expectedResponse, structs.DefaultEnterpriseMeta())
|
||||||
|
|
||||||
|
@ -391,8 +392,9 @@ func TestAgent_Service(t *testing.T) {
|
||||||
Port: 1818,
|
Port: 1818,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Meta: map[string]string{},
|
Meta: map[string]string{},
|
||||||
Tags: []string{},
|
Tags: []string{},
|
||||||
|
Datacenter: "dc1",
|
||||||
}
|
}
|
||||||
fillAgentServiceEnterpriseMeta(expectWebResponse, structs.DefaultEnterpriseMeta())
|
fillAgentServiceEnterpriseMeta(expectWebResponse, structs.DefaultEnterpriseMeta())
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,8 @@ type AgentService struct {
|
||||||
// to include the Namespace in the hash. When we do, then we are in for lots of fun with tests.
|
// to include the Namespace in the hash. When we do, then we are in for lots of fun with tests.
|
||||||
// For now though, ignoring it works well enough.
|
// For now though, ignoring it works well enough.
|
||||||
Namespace string `json:",omitempty" bexpr:"-" hash:"ignore"`
|
Namespace string `json:",omitempty" bexpr:"-" hash:"ignore"`
|
||||||
|
// Datacenter is only ever returned and is ignored if presented.
|
||||||
|
Datacenter string `json:",omitempty" bexpr:"-" hash:"ignore"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AgentServiceChecksInfo returns information about a Service and its checks
|
// AgentServiceChecksInfo returns information about a Service and its checks
|
||||||
|
|
|
@ -726,8 +726,9 @@ func TestAPI_AgentService(t *testing.T) {
|
||||||
Passing: 1,
|
Passing: 1,
|
||||||
Warning: 1,
|
Warning: 1,
|
||||||
},
|
},
|
||||||
Meta: map[string]string{},
|
Meta: map[string]string{},
|
||||||
Namespace: defaultNamespace,
|
Namespace: defaultNamespace,
|
||||||
|
Datacenter: "dc1",
|
||||||
}
|
}
|
||||||
require.Equal(expect, got)
|
require.Equal(expect, got)
|
||||||
require.Equal(expect.ContentHash, qm.LastContentHash)
|
require.Equal(expect.ContentHash, qm.LastContentHash)
|
||||||
|
|
|
@ -478,6 +478,7 @@ func (c *cmd) templateArgs() (*BootstrapTplArgs, error) {
|
||||||
LocalAgentClusterName: xds.LocalAgentClusterName,
|
LocalAgentClusterName: xds.LocalAgentClusterName,
|
||||||
Namespace: httpCfg.Namespace,
|
Namespace: httpCfg.Namespace,
|
||||||
EnvoyVersion: c.envoyVersion,
|
EnvoyVersion: c.envoyVersion,
|
||||||
|
Datacenter: httpCfg.Datacenter,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,15 +530,11 @@ func (c *cmd) generateConfig() ([]byte, error) {
|
||||||
// cluster is using namespaces regardless.
|
// cluster is using namespaces regardless.
|
||||||
args.Namespace = svc.Namespace
|
args.Namespace = svc.Namespace
|
||||||
}
|
}
|
||||||
agent, err := c.client.Agent().Self()
|
|
||||||
if err != nil {
|
if svc.Datacenter != "" {
|
||||||
return nil, fmt.Errorf("failed to fetch agent config: %v", err)
|
// The agent will definitely have the definitive answer here.
|
||||||
|
args.Datacenter = svc.Datacenter
|
||||||
}
|
}
|
||||||
dc, ok := agent["Config"]["Datacenter"].(string)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("failed to fetch datacenter from agent. DC is: %T", agent["Config"]["Datacenter"])
|
|
||||||
}
|
|
||||||
args.Datacenter = dc
|
|
||||||
|
|
||||||
if !c.disableCentralConfig {
|
if !c.disableCentralConfig {
|
||||||
// Parse the bootstrap config
|
// Parse the bootstrap config
|
||||||
|
|
|
@ -991,9 +991,10 @@ func testMockAgentGatewayConfig(namespacesEnabled bool) http.HandlerFunc {
|
||||||
|
|
||||||
svc := map[string]*api.AgentService{
|
svc := map[string]*api.AgentService{
|
||||||
string(kind): {
|
string(kind): {
|
||||||
Kind: kind,
|
Kind: kind,
|
||||||
ID: string(kind),
|
ID: string(kind),
|
||||||
Service: string(kind),
|
Service: string(kind),
|
||||||
|
Datacenter: "dc1",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1036,6 +1037,7 @@ func testMockAgentProxyConfig(cfg map[string]interface{}, namespacesEnabled bool
|
||||||
DestinationServiceID: serviceID,
|
DestinationServiceID: serviceID,
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
},
|
},
|
||||||
|
Datacenter: "dc1",
|
||||||
}
|
}
|
||||||
|
|
||||||
if namespacesEnabled {
|
if namespacesEnabled {
|
||||||
|
|
|
@ -74,6 +74,7 @@ $ curl \
|
||||||
"Port": 8000,
|
"Port": 8000,
|
||||||
"Address": "",
|
"Address": "",
|
||||||
"EnableTagOverride": false,
|
"EnableTagOverride": false,
|
||||||
|
"Datacenter": "dc1",
|
||||||
"Weights": {
|
"Weights": {
|
||||||
"Passing": 10,
|
"Passing": 10,
|
||||||
"Warning": 1
|
"Warning": 1
|
||||||
|
@ -185,6 +186,7 @@ $ curl \
|
||||||
"Warning": 1
|
"Warning": 1
|
||||||
},
|
},
|
||||||
"EnableTagOverride": false,
|
"EnableTagOverride": false,
|
||||||
|
"Datacenter": "dc1",
|
||||||
"ContentHash": "4ecd29c7bc647ca8",
|
"ContentHash": "4ecd29c7bc647ca8",
|
||||||
"Proxy": {
|
"Proxy": {
|
||||||
"DestinationServiceName": "web",
|
"DestinationServiceName": "web",
|
||||||
|
@ -304,6 +306,7 @@ curl localhost:8500/v1/agent/health/service/name/web
|
||||||
"Meta": null,
|
"Meta": null,
|
||||||
"Port": 80,
|
"Port": 80,
|
||||||
"EnableTagOverride": false,
|
"EnableTagOverride": false,
|
||||||
|
"Datacenter": "dc1",
|
||||||
"Connect": {
|
"Connect": {
|
||||||
"Native": false,
|
"Native": false,
|
||||||
"Proxy": null
|
"Proxy": null
|
||||||
|
@ -331,6 +334,7 @@ curl localhost:8500/v1/agent/health/service/name/web
|
||||||
"Meta": null,
|
"Meta": null,
|
||||||
"Port": 80,
|
"Port": 80,
|
||||||
"EnableTagOverride": false,
|
"EnableTagOverride": false,
|
||||||
|
"Datacenter": "dc1",
|
||||||
"Connect": {
|
"Connect": {
|
||||||
"Native": false,
|
"Native": false,
|
||||||
"Proxy": null
|
"Proxy": null
|
||||||
|
@ -380,6 +384,7 @@ curl localhost:8500/v1/agent/health/service/id/web2
|
||||||
"Meta": null,
|
"Meta": null,
|
||||||
"Port": 80,
|
"Port": 80,
|
||||||
"EnableTagOverride": false,
|
"EnableTagOverride": false,
|
||||||
|
"Datacenter": "dc1",
|
||||||
"Connect": {
|
"Connect": {
|
||||||
"Native": false,
|
"Native": false,
|
||||||
"Proxy": null
|
"Proxy": null
|
||||||
|
@ -425,6 +430,7 @@ curl localhost:8500/v1/agent/health/service/id/web1
|
||||||
"Meta": null,
|
"Meta": null,
|
||||||
"Port": 80,
|
"Port": 80,
|
||||||
"EnableTagOverride": false,
|
"EnableTagOverride": false,
|
||||||
|
"Datacenter": "dc1",
|
||||||
"Connect": {
|
"Connect": {
|
||||||
"Native": false,
|
"Native": false,
|
||||||
"Proxy": null
|
"Proxy": null
|
||||||
|
|
Loading…
Reference in New Issue