-
Notifications
You must be signed in to change notification settings - Fork 64
/
list.go
132 lines (110 loc) · 3.17 KB
/
list.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2024, Unikraft GmbH and The KraftKit Authors.
// Licensed under the BSD-3-Clause License (the "License").
// You may not use this file except in compliance with the License.
package list
import (
"context"
"fmt"
"sort"
"github.com/MakeNowJust/heredoc"
"github.com/spf13/cobra"
kraftcloud "sdk.kraft.cloud"
"kraftkit.sh/cmdfactory"
"kraftkit.sh/internal/cli/kraft/cloud/utils"
"kraftkit.sh/internal/tableprinter"
"kraftkit.sh/iostreams"
"kraftkit.sh/log"
)
type ListOptions struct {
Status bool `long:"status" short:"s" usage:"Also display the status of the metros"`
Output string `long:"output" short:"o" usage:"Set output format. Options: table,yaml,json,list" default:"table"`
}
func NewCmd() *cobra.Command {
cmd, err := cmdfactory.New(&ListOptions{}, cobra.Command{
Short: "List metros on KraftCloud",
Use: "list",
Args: cobra.NoArgs,
Aliases: []string{"ls"},
Long: heredoc.Doc(`
List metros on KraftCloud.
`),
Example: heredoc.Doc(`
# List metros available.
$ kraft cloud metro list
# List metros available in list format.
$ kraft cloud metro list -o list
# List metros available and their status.
$ kraft cloud metro list --status
`),
Annotations: map[string]string{
cmdfactory.AnnotationHelpGroup: "kraftcloud-metro",
},
})
if err != nil {
panic(err)
}
return cmd
}
func (opts *ListOptions) Pre(cmd *cobra.Command, _ []string) error {
if !utils.IsValidOutputFormat(opts.Output) {
return fmt.Errorf("invalid output format: %s", opts.Output)
}
return nil
}
func (opts *ListOptions) Run(ctx context.Context, args []string) error {
client := kraftcloud.NewMetrosClient()
metros, err := client.List(ctx, opts.Status)
if err != nil {
return fmt.Errorf("could not list metros: %w", err)
}
err = iostreams.G(ctx).StartPager()
if err != nil {
log.G(ctx).Errorf("error starting pager: %v", err)
}
defer iostreams.G(ctx).StopPager()
cs := iostreams.G(ctx).ColorScheme()
table, err := tableprinter.NewTablePrinter(ctx,
tableprinter.WithMaxWidth(iostreams.G(ctx).TerminalWidth()),
tableprinter.WithOutputFormatFromString(opts.Output),
)
if err != nil {
return err
}
// Sort the metros by delay.
if opts.Status {
sort.Slice(metros, func(i, j int) bool {
return metros[i].Delay < metros[j].Delay
})
// Move the offline metros to the end of the list.
sort.SliceStable(metros, func(i, j int) bool {
return metros[i].Online && !metros[j].Online
})
}
// Header row
table.AddField("CODE", cs.Bold)
table.AddField("IPV4", cs.Bold)
table.AddField("LOCATION", cs.Bold)
table.AddField("PROXY", cs.Bold)
if opts.Status {
table.AddField("STATUS", cs.Bold)
table.AddField("PING", cs.Bold)
}
table.EndRow()
for _, metro := range metros {
table.AddField(metro.Code, nil)
table.AddField(metro.Ipv4, nil)
table.AddField(metro.Location, nil)
table.AddField(metro.Proxy, nil)
if opts.Status {
if metro.Online {
table.AddField("online", cs.Green)
} else {
table.AddField("offline", cs.Red)
}
table.AddField(fmt.Sprintf("%d MS", metro.Delay.Milliseconds()), nil)
}
table.EndRow()
}
return table.Render(iostreams.G(ctx).Out)
}