-
Notifications
You must be signed in to change notification settings - Fork 235
/
status.go
145 lines (115 loc) · 2.88 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
144
145
// Package status implements the status command chain.
package status
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"strings"
"time"
"github.com/azazeal/pause"
"github.com/inancgumus/screen"
"github.com/spf13/cobra"
"github.com/superfly/flyctl/iostreams"
"github.com/superfly/flyctl/internal/appconfig"
"github.com/superfly/flyctl/internal/command"
"github.com/superfly/flyctl/internal/config"
"github.com/superfly/flyctl/internal/flag"
"github.com/superfly/flyctl/internal/flyutil"
)
func New() (cmd *cobra.Command) {
const (
long = `Show the application's current status including application
details, tasks, most recent deployment details and in which regions it is
currently allocated.
`
short = "Show app status"
)
cmd = command.New("status", short, long, run,
command.RequireSession,
command.RequireAppName,
)
cmd.Args = cobra.NoArgs
flag.Add(cmd,
flag.App(),
flag.AppConfig(),
flag.JSONOutput(),
flag.Bool{
Name: "all",
Description: "Show completed instances",
},
flag.Bool{
Name: "deployment",
Description: "Always show deployment status",
},
flag.Bool{
Name: "watch",
Description: "Refresh details",
},
flag.Int{
Name: "rate",
Description: "Refresh Rate for --watch",
Default: 5,
},
)
return
}
func run(ctx context.Context) error {
watch := flag.GetBool(ctx, "watch")
if watch && config.FromContext(ctx).JSONOutput {
return errors.New("--watch and --json are not supported together")
}
if !watch {
return runOnce(ctx)
}
return runWatch(ctx)
}
func runOnce(ctx context.Context) error {
return once(ctx, iostreams.FromContext(ctx).Out)
}
func once(ctx context.Context, out io.Writer) (err error) {
var (
appName = appconfig.NameFromContext(ctx)
client = flyutil.ClientFromContext(ctx)
)
app, err := client.GetAppCompact(ctx, appName)
if err != nil {
return fmt.Errorf("failed to get app: %w", err)
}
return RenderMachineStatus(ctx, app, out)
}
func runWatch(ctx context.Context) (err error) {
streams := iostreams.FromContext(ctx)
if !streams.IsInteractive() {
err = errors.New("--watch is not supported for non-interactive sessions")
return
}
colorize := streams.ColorScheme()
sleep := flag.GetInt(ctx, "rate")
if sleep < 1 || sleep > 3600 {
err = errors.New("--rate must be in the [1, 3600] range")
return
}
appName := appconfig.NameFromContext(ctx)
var buf bytes.Buffer
for err == nil {
buf.Reset()
if err = once(ctx, &buf); err != nil {
break
}
header := fmt.Sprintf("%s %s %s\n\n", colorize.Bold(appName), "at:", colorize.Bold(time.Now().UTC().Format("15:04:05")))
screen.Clear()
screen.MoveTopLeft()
io.Copy(streams.Out, io.MultiReader(
strings.NewReader(header),
&buf,
))
pause.For(ctx, time.Duration(sleep)*time.Second)
}
// Interrupted with Ctrl-C
if errors.Is(ctx.Err(), context.Canceled) {
err = nil
}
return
}