Add cluster command to show cluster and peer statuses. (#2256)

Signed-off-by: Fahri Yardımcı <f.yardimci06@gmail.com>

Signed-off-by: Fahri Yardımcı <f.yardimci06@gmail.com>
This commit is contained in:
Fahri YARDIMCI 2020-05-18 16:25:15 +03:00 committed by GitHub
parent de80d907d1
commit 12db463c7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 100 additions and 0 deletions

43
cli/cluster.go Normal file
View File

@ -0,0 +1,43 @@
// Copyright 2020 Prometheus Team
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cli
import (
"context"
"errors"
"gopkg.in/alecthomas/kingpin.v2"
"github.com/prometheus/alertmanager/cli/format"
)
const clusterHelp = `View cluster status and peers.`
// clusterCmd represents the cluster command
func configureClusterCmd(app *kingpin.Application) {
clusterCmd := app.Command("cluster", clusterHelp)
clusterCmd.Command("show", clusterHelp).Default().Action(execWithTimeout(showStatus)).PreAction(requireAlertManagerURL)
}
func showStatus(ctx context.Context, _ *kingpin.ParseContext) error {
alertManagerStatus, err := getRemoteAlertmanagerConfigStatus(ctx, alertmanagerURL)
if err != nil {
return err
}
formatter, found := format.Formatters[output]
if !found {
return errors.New("unknown output formatter")
}
return formatter.FormatClusterStatus(alertManagerStatus.Cluster)
}

View File

@ -39,6 +39,7 @@ type Formatter interface {
FormatSilences([]models.GettableSilence) error
FormatAlerts([]*models.GettableAlert) error
FormatConfig(*models.AlertmanagerStatus) error
FormatClusterStatus(status *models.ClusterStatus) error
}
// Formatters is a map of cli argument names to formatter interface object.

View File

@ -89,6 +89,27 @@ func (formatter *ExtendedFormatter) FormatConfig(status *models.AlertmanagerStat
return nil
}
// FormatClusterStatus formats the cluster status with peers into a readable string.
func (formatter *ExtendedFormatter) FormatClusterStatus(status *models.ClusterStatus) error {
w := tabwriter.NewWriter(formatter.writer, 0, 0, 2, ' ', 0)
fmt.Fprintf(w,
"Cluster Status:\t%s\nNode Name:\t%s\n\n",
*status.Status,
status.Name,
)
fmt.Fprintln(w, "Address\tName")
sort.Sort(ByAddress(status.Peers))
for _, peer := range status.Peers {
fmt.Fprintf(
w,
"%s\t%s\t\n",
*peer.Address,
*peer.Name,
)
}
return w.Flush()
}
func extendedFormatLabels(labels models.LabelSet) string {
output := []string{}
for name, value := range labels {

View File

@ -47,3 +47,8 @@ func (formatter *JSONFormatter) FormatConfig(status *models.AlertmanagerStatus)
enc := json.NewEncoder(formatter.writer)
return enc.Encode(status)
}
func (formatter *JSONFormatter) FormatClusterStatus(status *models.ClusterStatus) error {
enc := json.NewEncoder(formatter.writer)
return enc.Encode(status)
}

View File

@ -75,6 +75,16 @@ func (formatter *SimpleFormatter) FormatConfig(status *models.AlertmanagerStatus
return nil
}
func (formatter *SimpleFormatter) FormatClusterStatus(status *models.ClusterStatus) error {
w := tabwriter.NewWriter(formatter.writer, 0, 0, 2, ' ', 0)
fmt.Fprintf(w,
"Cluster Status:\t%s\nNode Name:\t%s\n",
*status.Status,
status.Name,
)
return w.Flush()
}
func simpleFormatMatchers(matchers models.Matchers) string {
output := []string{}
for _, matcher := range matchers {

View File

@ -14,6 +14,9 @@
package format
import (
"bytes"
"net"
"strconv"
"time"
"github.com/prometheus/alertmanager/api/v2/models"
@ -34,3 +37,19 @@ func (s ByStartsAt) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ByStartsAt) Less(i, j int) bool {
return time.Time(*s[i].StartsAt).Before(time.Time(*s[j].StartsAt))
}
type ByAddress []*models.PeerStatus
func (s ByAddress) Len() int { return len(s) }
func (s ByAddress) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s ByAddress) Less(i, j int) bool {
ip1, port1, _ := net.SplitHostPort(*s[i].Address)
ip2, port2, _ := net.SplitHostPort(*s[j].Address)
if ip1 == ip2 {
p1, _ := strconv.Atoi(port1)
p2, _ := strconv.Atoi(port2)
return p1 < p2
} else {
return bytes.Compare(net.ParseIP(ip1), net.ParseIP(ip2)) < 0
}
}

View File

@ -111,6 +111,7 @@ func Execute() {
configureAlertCmd(app)
configureSilenceCmd(app)
configureCheckConfigCmd(app)
configureClusterCmd(app)
configureConfigCmd(app)
err = resolver.Bind(app, os.Args[1:])