Fix consul catalog panic when health and services are not in sync

Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
This commit is contained in:
Harold Ozouf 2020-11-17 17:30:03 +01:00 committed by GitHub
parent 52eeff9f9f
commit 9177982334
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -170,17 +170,22 @@ func (p *Provider) getConsulServicesData(ctx context.Context) ([]itemData, error
var data []itemData
for _, name := range consulServiceNames {
consulServices, healthServices, err := p.fetchService(ctx, name)
consulServices, statuses, err := p.fetchService(ctx, name)
if err != nil {
return nil, err
}
for i, consulService := range consulServices {
for _, consulService := range consulServices {
address := consulService.ServiceAddress
if address == "" {
address = consulService.Address
}
status, exists := statuses[consulService.ID+consulService.ServiceID]
if !exists {
status = api.HealthAny
}
item := itemData{
ID: consulService.ServiceID,
Node: consulService.Node,
@ -189,7 +194,7 @@ func (p *Provider) getConsulServicesData(ctx context.Context) ([]itemData, error
Port: strconv.Itoa(consulService.ServicePort),
Labels: tagsToNeutralLabels(consulService.ServiceTags, p.Prefix),
Tags: consulService.ServiceTags,
Status: healthServices[i].Checks.AggregatedStatus(),
Status: status,
}
extraConf, err := p.getConfiguration(item)
@ -205,13 +210,14 @@ func (p *Provider) getConsulServicesData(ctx context.Context) ([]itemData, error
return data, nil
}
func (p *Provider) fetchService(ctx context.Context, name string) ([]*api.CatalogService, []*api.ServiceEntry, error) {
func (p *Provider) fetchService(ctx context.Context, name string) ([]*api.CatalogService, map[string]string, error) {
var tagFilter string
if !p.ExposedByDefault {
tagFilter = p.Prefix + ".enable=true"
}
opts := &api.QueryOptions{AllowStale: p.Stale, RequireConsistent: p.RequireConsistent, UseCache: p.Cache}
opts = opts.WithContext(ctx)
consulServices, _, err := p.client.Catalog().Service(name, tagFilter, opts)
if err != nil {
@ -219,7 +225,22 @@ func (p *Provider) fetchService(ctx context.Context, name string) ([]*api.Catalo
}
healthServices, _, err := p.client.Health().Service(name, tagFilter, false, opts)
return consulServices, healthServices, err
if err != nil {
return nil, nil, err
}
// Index status by service and node so it can be retrieved from a CatalogService even if the health and services
// are not in sync.
statuses := make(map[string]string)
for _, health := range healthServices {
if health.Service == nil || health.Node == nil {
continue
}
statuses[health.Node.ID+health.Service.ID] = health.Checks.AggregatedStatus()
}
return consulServices, statuses, err
}
func (p *Provider) fetchServices(ctx context.Context) ([]string, error) {