/
status.go
143 lines (120 loc) · 3.46 KB
/
status.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
133
134
135
136
137
138
139
140
141
142
143
package webspace
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"strings"
"text/template"
"time"
"github.com/dustin/go-humanize"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
"github.com/netsoc/cli/pkg/config"
"github.com/netsoc/cli/pkg/util"
webspaced "github.com/netsoc/webspaced/client"
)
type statusOptions struct {
Config func() (*config.Config, error)
WebspacedClient func() (*webspaced.APIClient, error)
OutputFormat string
User string
}
// NewCmdStatus creates a new webspace status command
func NewCmdStatus(f *util.CmdFactory) *cobra.Command {
opts := statusOptions{
Config: f.Config,
WebspacedClient: f.WebspacedClient,
}
cmd := &cobra.Command{
Use: "status",
Aliases: []string{"state"},
Short: "Get status",
RunE: func(cmd *cobra.Command, args []string) error {
return statusRun(opts)
},
}
cmd.Flags().StringVarP(&opts.OutputFormat, "output", "o", "text", "output format `text|yaml|json|template=<Go template>`")
util.AddOptUser(cmd, &opts.User)
return cmd
}
func printState(state webspaced.State, outputType string) error {
if strings.HasPrefix(outputType, "template=") {
tpl, err := template.New("anonymous").Parse(strings.TrimPrefix(outputType, "template="))
if err != nil {
return fmt.Errorf("failed to parse template: %w", err)
}
if err := tpl.Execute(os.Stdout, state); err != nil {
return fmt.Errorf("failed to execute template: %w", err)
}
return nil
}
switch outputType {
case "json":
if err := json.NewEncoder(os.Stdout).Encode(state); err != nil {
return fmt.Errorf("failed to encode JSON: %w", err)
}
case "yaml":
if err := yaml.NewEncoder(os.Stdout).Encode(state); err != nil {
return fmt.Errorf("failed to encode YAML: %w", err)
}
case "text":
running := "no"
if state.Running {
running = "yes"
}
fmt.Printf("Running: %v\n", running)
if len(state.Usage.Disks) > 0 {
fmt.Println("Disks:")
for n, usage := range state.Usage.Disks {
fmt.Printf(" - %v: Used %v\n", n, humanize.IBytes(uint64(usage)))
}
}
if state.Running {
fmt.Printf("Uptime: %v\n", time.Duration(state.Uptime*float64(time.Second.Nanoseconds())))
fmt.Printf("CPU time: %v\n", time.Duration(state.Usage.Cpu))
fmt.Printf("Memory usage: %v\n", humanize.IBytes(uint64(state.Usage.Memory)))
fmt.Printf("Running processes: %v\n", state.Usage.Processes)
if len(state.NetworkInterfaces) > 0 {
fmt.Println("Network interfaces:")
for n, iface := range state.NetworkInterfaces {
fmt.Printf(" - %v (%v)\n", n, iface.Mac)
fmt.Printf(" Sent/received: %v/%v\n",
humanize.IBytes(uint64(iface.Counters.BytesSent)),
humanize.IBytes(uint64(iface.Counters.BytesReceived)),
)
for _, addr := range iface.Addresses {
t := "IPv4"
if addr.Family == "inet6" {
t = "IPv6"
}
fmt.Printf(" %v address: %v/%v\n", t, addr.Address, addr.Netmask)
}
}
}
}
default:
return fmt.Errorf(`unknown output format "%v"`, outputType)
}
return nil
}
func statusRun(opts statusOptions) error {
c, err := opts.Config()
if err != nil {
return err
}
if c.Token == "" {
return errors.New("not logged in")
}
client, err := opts.WebspacedClient()
if err != nil {
return err
}
ctx := context.WithValue(context.Background(), webspaced.ContextAccessToken, c.Token)
state, _, err := client.StateApi.GetState(ctx, opts.User)
if err != nil {
return util.APIError(err)
}
return printState(state, opts.OutputFormat)
}