@@ -22,17 +22,12 @@ package resources
2222
2323import (
2424 "context"
25- goStrings "strings"
26- "sync"
2725
2826 core "k8s.io/api/core/v1"
2927 meta "k8s.io/apimachinery/pkg/apis/meta/v1"
30- "k8s.io/apimachinery/pkg/types"
3128
3229 api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
33- "github.com/arangodb/kube-arangodb/pkg/deployment/features"
3430 "github.com/arangodb/kube-arangodb/pkg/deployment/patch"
35- "github.com/arangodb/kube-arangodb/pkg/util/arangod"
3631 "github.com/arangodb/kube-arangodb/pkg/util/errors"
3732 "github.com/arangodb/kube-arangodb/pkg/util/globals"
3833 "github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
@@ -46,7 +41,7 @@ import (
4641// consequentially service will not point to any pod.
4742// It works only in active fail-over mode.
4843func (r * Resources ) EnsureLeader (ctx context.Context , cachedStatus inspectorInterface.Inspector ) error {
49- if r .context .GetSpec ().GetMode () != api . DeploymentModeActiveFailover {
44+ if ! r .context .GetSpec ().GetMode (). HasAgents () {
5045 return nil
5146 }
5247
@@ -129,7 +124,7 @@ func (r *Resources) EnsureLeader(ctx context.Context, cachedStatus inspectorInte
129124 return err
130125 } else {
131126 if ! c {
132- return r . ensureSingleServerLeader ( ctx , cachedStatus )
127+ return nil
133128 }
134129
135130 return errors .Reconcile ()
@@ -150,170 +145,3 @@ func (r *Resources) EnsureLeader(ctx context.Context, cachedStatus inspectorInte
150145 // The service has been created.
151146 return errors .Reconcile ()
152147}
153-
154- // getSingleServerLeaderID returns ids of a single server leaders.
155- func (r * Resources ) getSingleServerLeaderID (ctx context.Context ) ([]string , error ) {
156- status := r .context .GetStatus ()
157- var mutex sync.Mutex
158- var leaderIDs []string
159- var anyError error
160-
161- ctxCancel , cancel := context .WithCancel (ctx )
162- defer cancel ()
163-
164- var wg sync.WaitGroup
165- for _ , m := range status .Members .Single {
166- wg .Add (1 )
167- go func (id string ) {
168- defer wg .Done ()
169- err := globals .GetGlobalTimeouts ().ArangoD ().RunWithTimeout (ctxCancel , func (ctxChild context.Context ) error {
170- c , err := r .context .GetMembersState ().GetMemberClient (id )
171- if err != nil {
172- return err
173- }
174-
175- if available , err := arangod .IsServerAvailable (ctxChild , c ); err != nil {
176- return err
177- } else if ! available {
178- return errors .New ("not available" )
179- }
180-
181- mutex .Lock ()
182- leaderIDs = append (leaderIDs , id )
183- mutex .Unlock ()
184- return nil
185- })
186-
187- if err != nil {
188- mutex .Lock ()
189- anyError = err
190- mutex .Unlock ()
191- }
192- }(m .ID )
193- }
194- wg .Wait ()
195-
196- if len (leaderIDs ) > 0 {
197- return leaderIDs , nil
198- }
199-
200- if anyError != nil {
201- return nil , errors .WithMessagef (anyError , "unable to get a leader" )
202- }
203-
204- return nil , errors .New ("unable to get a leader" )
205- }
206-
207- // setSingleServerLeadership adds or removes leadership label on a single server pod.
208- func (r * Resources ) ensureSingleServerLeader (ctx context.Context , cachedStatus inspectorInterface.Inspector ) error {
209- changed := false
210-
211- enabled := features .FailoverLeadership ().Enabled ()
212- var leaderID string
213- if enabled {
214- leaderIDs , err := r .getSingleServerLeaderID (ctx )
215- if err != nil {
216- return err
217- }
218-
219- if len (leaderIDs ) == 1 {
220- leaderID = leaderIDs [0 ]
221- } else if len (leaderIDs ) > 1 {
222- r .log .Error ("multiple leaders found: %s. Blocking traffic to the deployment services" , goStrings .Join (leaderIDs , ", " ))
223- }
224- }
225-
226- status := r .context .GetStatus ()
227- for _ , m := range status .Members .Single {
228- pod , exist := cachedStatus .Pod ().V1 ().GetSimple (m .Pod .GetName ())
229- if ! exist {
230- continue
231- }
232-
233- labels := pod .GetLabels ()
234- if enabled && m .ID == leaderID {
235- if value , ok := labels [k8sutil .LabelKeyArangoLeader ]; ok && value == "true" {
236- // Single server is available, and it has a leader label.
237- continue
238- }
239-
240- labels = addLabel (labels , k8sutil .LabelKeyArangoLeader , "true" )
241- } else {
242- if _ , ok := labels [k8sutil .LabelKeyArangoLeader ]; ! ok {
243- // Single server is not available, and it does not have a leader label.
244- continue
245- }
246-
247- delete (labels , k8sutil .LabelKeyArangoLeader )
248- }
249-
250- err := r .context .ApplyPatchOnPod (ctx , pod , patch .ItemReplace (patch .NewPath ("metadata" , "labels" ), labels ))
251- if err != nil {
252- return errors .WithMessagef (err , "unable to change leader label for pod %s" , m .Pod .GetName ())
253- }
254- changed = true
255- }
256-
257- if changed {
258- return errors .Reconcile ()
259- }
260-
261- return r .ensureSingleServerLeaderServices (ctx , cachedStatus )
262- }
263-
264- // ensureSingleServerLeaderServices adds a leadership label to deployment service and external deployment service.
265- func (r * Resources ) ensureSingleServerLeaderServices (ctx context.Context , cachedStatus inspectorInterface.Inspector ) error {
266- // Add a leadership label to deployment service and external deployment service.
267- deploymentName := r .context .GetAPIObject ().GetName ()
268- changed := false
269- services := []string {
270- k8sutil .CreateDatabaseClientServiceName (deploymentName ),
271- k8sutil .CreateDatabaseExternalAccessServiceName (deploymentName ),
272- }
273-
274- enabled := features .FailoverLeadership ().Enabled ()
275- for _ , svcName := range services {
276- svc , exists := cachedStatus .Service ().V1 ().GetSimple (svcName )
277- if ! exists {
278- // It will be created later with a leadership label.
279- continue
280- }
281- selector := svc .Spec .Selector
282- if enabled {
283- if v , ok := selector [k8sutil .LabelKeyArangoLeader ]; ok && v == "true" {
284- // It is already OK.
285- continue
286- }
287-
288- selector = addLabel (selector , k8sutil .LabelKeyArangoLeader , "true" )
289- } else {
290- if _ , ok := selector [k8sutil .LabelKeyArangoLeader ]; ! ok {
291- // Service does not have a leader label, and it should not have.
292- continue
293- }
294-
295- delete (selector , k8sutil .LabelKeyArangoLeader )
296- }
297-
298- parser := patch .Patch ([]patch.Item {patch .ItemReplace (patch .NewPath ("spec" , "selector" ), selector )})
299- data , err := parser .Marshal ()
300- if err != nil {
301- return errors .WithMessagef (err , "unable to marshal labels for service %s" , svcName )
302- }
303-
304- err = globals .GetGlobalTimeouts ().Kubernetes ().RunWithTimeout (ctx , func (ctxChild context.Context ) error {
305- _ , err := cachedStatus .ServicesModInterface ().V1 ().Patch (ctxChild , svcName , types .JSONPatchType , data , meta.PatchOptions {})
306- return err
307- })
308- if err != nil {
309- return errors .WithMessagef (err , "unable to patch labels for service %s" , svcName )
310- }
311- changed = true
312- }
313-
314- if changed {
315- return errors .Reconcile ()
316- }
317-
318- return nil
319- }
0 commit comments