Skip to content

Commit 5fcc416

Browse files
authored
Merge pull request #13 from n-marton/feat/cleanup
add functionality cleanup tags on other nodes
2 parents f66b2b6 + e4d341b commit 5fcc416

File tree

1 file changed

+83
-12
lines changed

1 file changed

+83
-12
lines changed

internal/ballot/ballot.go

Lines changed: 83 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ package ballot
33
import (
44
"encoding/json"
55
"fmt"
6+
"os/exec"
7+
"sync/atomic"
8+
"time"
9+
610
"github.com/google/shlex"
711
"github.com/hashicorp/consul/api"
812
"github.com/hashicorp/consul/api/watch"
913
log "github.com/sirupsen/logrus"
1014
"golang.org/x/exp/slices"
1115
"golang.org/x/net/context"
12-
"os/exec"
13-
"sync/atomic"
14-
"time"
1516
)
1617

1718
type ElectionPayload struct {
@@ -86,6 +87,31 @@ func (b *Ballot) copyServiceToRegistration(service *api.AgentService) *api.Agent
8687
}
8788
}
8889

90+
func (b *Ballot) copyCatalogServiceToRegistration(service *api.CatalogService) *api.CatalogRegistration {
91+
return &api.CatalogRegistration{
92+
ID: service.ID,
93+
Node: service.Node,
94+
Address: service.ServiceAddress,
95+
TaggedAddresses: service.TaggedAddresses,
96+
NodeMeta: service.NodeMeta,
97+
Datacenter: service.Datacenter,
98+
Service: &api.AgentService{
99+
ID: service.ServiceID,
100+
Service: service.ServiceName,
101+
Tags: service.ServiceTags,
102+
Meta: service.ServiceMeta,
103+
Port: service.ServicePort,
104+
Address: service.ServiceAddress,
105+
TaggedAddresses: service.ServiceTaggedAddresses,
106+
Weights: api.AgentWeights{
107+
Passing: service.ServiceWeights.Passing,
108+
Warning: service.ServiceWeights.Warning,
109+
},
110+
EnableTagOverride: service.ServiceEnableTagOverride,
111+
},
112+
}
113+
}
114+
89115
// Run starts the leader election.
90116
func (b *Ballot) Run() (err error) {
91117
b.ctx = context.Background()
@@ -102,22 +128,26 @@ func (b *Ballot) Run() (err error) {
102128
}
103129

104130
// getService returns the registered service.
105-
func (b *Ballot) getService() (service *api.AgentService, err error) {
131+
func (b *Ballot) getService() (service *api.AgentService, catalogServices []*api.CatalogService, err error) {
106132
agent := b.client.Agent()
107-
services, err := agent.Services()
133+
service, _, err = agent.Service(b.ID, &api.QueryOptions{})
108134
if err != nil {
109-
return service, err
135+
return service, nil, err
110136
}
111-
service, ok := services[b.ID]
112-
if !ok {
113-
return service, fmt.Errorf("service %s not found", b.ID)
137+
if service == nil {
138+
return service, nil, fmt.Errorf("service %s not found", b.ID)
114139
}
115-
return service, err
140+
catalog := b.client.Catalog()
141+
catalogServices, _, err = catalog.Service(b.ID, b.PrimaryTag, &api.QueryOptions{})
142+
if err != nil {
143+
return service, nil, err
144+
}
145+
return service, catalogServices, err
116146
}
117147

118148
// updateServiceTags updates the service tags.
119149
func (b *Ballot) updateServiceTags() error {
120-
service, err := b.getService()
150+
service, _, err := b.getService()
121151
if err != nil {
122152
return err
123153
}
@@ -156,6 +186,42 @@ func (b *Ballot) updateServiceTags() error {
156186
return err
157187
}
158188

189+
// cleanup is called on promote, it cleans up tags on the instances of the service, useful if an other ballot stopped unexpectedly
190+
func (b *Ballot) cleanup() error {
191+
service, catalogServices, err := b.getService()
192+
if err != nil {
193+
return err
194+
}
195+
for _, catcatalogService := range catalogServices {
196+
if catcatalogService.Address != service.Address {
197+
p := slices.Index(catcatalogService.ServiceTags, b.PrimaryTag)
198+
if p == -1 {
199+
return nil
200+
}
201+
log.WithFields(log.Fields{
202+
"caller": "cleanupCatalogServiceTags",
203+
"service": b.ID,
204+
"node": catcatalogService.Node,
205+
"tags": catcatalogService.ServiceTags,
206+
}).Debug("current service tags")
207+
catcatalogService.ServiceTags = slices.Delete(catcatalogService.ServiceTags, p, p+1)
208+
catalog := b.client.Catalog()
209+
reg := b.copyCatalogServiceToRegistration(catcatalogService)
210+
_, err := catalog.Register(reg, &api.WriteOptions{})
211+
if err != nil {
212+
return err
213+
}
214+
log.WithFields(log.Fields{
215+
"caller": "cleanupCatalogServiceTags",
216+
"service": b.ID,
217+
"node": catcatalogService.Node,
218+
"tags": catcatalogService.ServiceTags,
219+
}).Debug("new service tags")
220+
}
221+
}
222+
return nil
223+
}
224+
159225
// onPromote is called when the node is promoted to leader.
160226
func (b *Ballot) onPromote() (err error) {
161227
b.leader.Store(true)
@@ -164,6 +230,11 @@ func (b *Ballot) onPromote() (err error) {
164230
b.releaseSession()
165231
return fmt.Errorf("failed to update service tags: %s", err)
166232
}
233+
err = b.cleanup()
234+
if err != nil {
235+
b.releaseSession()
236+
return fmt.Errorf("failed to cleanup old service tags: %s", err)
237+
}
167238
return err
168239
}
169240

@@ -182,7 +253,7 @@ func (b *Ballot) election() (err error) {
182253

183254
if !b.leader.Load() {
184255
if b.sessionID.Load() != nil {
185-
service, err := b.getService()
256+
service, _, err := b.getService()
186257
if err != nil {
187258
return fmt.Errorf("failed to get service: %s", err)
188259
}

0 commit comments

Comments
 (0)