/
maintenance.go
106 lines (85 loc) · 2.67 KB
/
maintenance.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Copyright (c) 2020-2022, R.I. Pienaar and the Choria Project contributors
//
// SPDX-License-Identifier: Apache-2.0
package scoutcmd
import (
"context"
"fmt"
"os"
"strings"
"sync"
"github.com/choria-io/go-choria/inter"
iu "github.com/choria-io/go-choria/internal/util"
"github.com/sirupsen/logrus"
"github.com/choria-io/go-choria/client/discovery"
"github.com/choria-io/go-choria/client/scoutclient"
scoutagent "github.com/choria-io/go-choria/scout/agent/scout"
)
type MaintenanceCommand struct {
fw inter.Framework
sopt *discovery.StandardOptions
checks []string
json bool
verbose bool
colorize bool
log *logrus.Entry
}
func NewMaintenanceCommand(sopt *discovery.StandardOptions, fw inter.Framework, checks []string, json bool, verbose bool, colorize bool, log *logrus.Entry) (*MaintenanceCommand, error) {
return &MaintenanceCommand{
fw: fw,
sopt: sopt,
checks: checks,
json: json,
log: log,
verbose: verbose,
colorize: colorize,
}, nil
}
func (t *MaintenanceCommand) Run(ctx context.Context, wg *sync.WaitGroup) error {
defer wg.Done()
sc, err := scoutClient(t.fw, t.sopt, t.log)
if err != nil {
return err
}
var checks = make([]any, len(t.checks))
for i, c := range t.checks {
checks[i] = c
}
result, err := sc.Maintenance().Checks(checks).Do(ctx)
if err != nil {
return err
}
if t.json {
return result.RenderResults(os.Stdout, scoutclient.JSONFormat, scoutclient.DisplayDDL, t.verbose, false, t.colorize, t.log)
}
if result.Stats().ResponsesCount() == 0 {
return fmt.Errorf("no responses received")
}
mu := sync.Mutex{}
triggered := 0
shown := 0
table := iu.NewUTF8TableWithTitle("Scout check maintenance", "Name", "Triggered", "Skipped", "Failed", "Message")
result.EachOutput(func(r *scoutclient.MaintenanceOutput) {
tr := &scoutagent.TriggerReply{}
err = r.ParseMaintenanceOutput(tr)
if err != nil {
t.log.Errorf("Could not parse output from %s: %s", r.ResultDetails().Sender(), err)
return
}
mu.Lock()
defer mu.Unlock()
triggered += len(tr.TransitionedChecks)
if !t.verbose && r.ResultDetails().OK() && len(tr.FailedChecks) == 0 {
return
}
shown++
table.AddRow(r.ResultDetails().Sender(), strings.Join(tr.TransitionedChecks, ", "), strings.Join(tr.SkippedChecks, ", "), strings.Join(tr.FailedChecks, ", "), r.ResultDetails().StatusMessage())
})
if shown == 0 {
fmt.Printf("Placed %d checks into maintenance mode on %d nodes\n", triggered, result.Stats().ResponsesCount())
fmt.Println()
} else {
fmt.Println(table.Render())
}
return result.RenderResults(os.Stdout, scoutclient.TXTFooter, scoutclient.DisplayDDL, t.verbose, false, t.colorize, t.log)
}