5
5
"io"
6
6
"time"
7
7
8
- "github.com/jedib0t/go-pretty/v6/table"
9
8
"golang.org/x/xerrors"
10
9
11
10
"github.com/coder/coder/v2/cli/clibase"
@@ -17,7 +16,7 @@ import (
17
16
)
18
17
19
18
const (
20
- scheduleShowDescriptionLong = `Shows the following information for the given workspace:
19
+ scheduleShowDescriptionLong = `Shows the following information for the given workspace(s) :
21
20
* The automatic start schedule
22
21
* The next scheduled start time
23
22
* The duration after which it will stop
@@ -72,25 +71,57 @@ func (r *RootCmd) schedules() *clibase.Cmd {
72
71
return scheduleCmd
73
72
}
74
73
74
+ // scheduleShow() is just a wrapper for list() with some different defaults.
75
75
func (r * RootCmd ) scheduleShow () * clibase.Cmd {
76
+ var (
77
+ filter cliui.WorkspaceFilter
78
+ formatter = cliui .NewOutputFormatter (
79
+ cliui .TableFormat (
80
+ []scheduleListRow {},
81
+ []string {
82
+ "workspace" ,
83
+ "starts at" ,
84
+ "starts next" ,
85
+ "stops after" ,
86
+ "stops next" ,
87
+ },
88
+ ),
89
+ cliui .JSONFormat (),
90
+ )
91
+ )
76
92
client := new (codersdk.Client )
77
93
showCmd := & clibase.Cmd {
78
- Use : "show <workspace-name >" ,
79
- Short : "Show workspace schedule " ,
94
+ Use : "show <workspace 1> ... <workspace N >" ,
95
+ Short : "Show workspace schedules " ,
80
96
Long : scheduleShowDescriptionLong ,
81
97
Middleware : clibase .Chain (
82
- clibase .RequireNArgs ( 1 ),
98
+ clibase .RequireRangeArgs ( 0 , 1 ),
83
99
r .InitClient (client ),
84
100
),
85
101
Handler : func (inv * clibase.Invocation ) error {
86
- workspace , err := namedWorkspace (inv .Context (), client , inv .Args [0 ])
102
+ // To preserve existing behavior, if an argument is passed we will
103
+ // only show the schedule for that workspace.
104
+ // This will clobber the search query if one is passed.
105
+ f := filter .Filter ()
106
+ if len (inv .Args ) == 1 {
107
+ f .FilterQuery = fmt .Sprintf ("owner:me name:%s" , inv .Args [0 ])
108
+ }
109
+ res , err := queryConvertWorkspaces (inv .Context (), client , f , scheduleListRowFromWorkspace )
110
+ if err != nil {
111
+ return err
112
+ }
113
+
114
+ out , err := formatter .Format (inv .Context (), res )
87
115
if err != nil {
88
116
return err
89
117
}
90
118
91
- return displaySchedule (workspace , inv .Stdout )
119
+ _ , err = fmt .Fprintln (inv .Stdout , out )
120
+ return err
92
121
},
93
122
}
123
+ filter .AttachOptions (& showCmd .Options )
124
+ formatter .AttachOptions (& showCmd .Options )
94
125
return showCmd
95
126
}
96
127
@@ -242,50 +273,52 @@ func (r *RootCmd) scheduleOverride() *clibase.Cmd {
242
273
return overrideCmd
243
274
}
244
275
245
- func displaySchedule (workspace codersdk.Workspace , out io.Writer ) error {
246
- loc , err := tz .TimezoneIANA ()
276
+ func displaySchedule (ws codersdk.Workspace , out io.Writer ) error {
277
+ rows := []workspaceListRow {workspaceListRowFromWorkspace (time .Now (), ws )}
278
+ rendered , err := cliui .DisplayTable (rows , "workspace" , []string {
279
+ "workspace" , "starts at" , "starts next" , "stops after" , "stops next" ,
280
+ })
247
281
if err != nil {
248
- loc = time . UTC // best effort
282
+ return err
249
283
}
284
+ _ , _ = fmt .Fprintln (out , rendered )
285
+ return nil
286
+ }
250
287
251
- var (
252
- schedStart = "manual"
253
- schedStop = "manual"
254
- schedNextStart = "-"
255
- schedNextStop = "-"
256
- )
288
+ // scheduleListRow is a row in the schedule list.
289
+ // this is required for proper JSON output.
290
+ type scheduleListRow struct {
291
+ WorkspaceName string `json:"workspace" table:"workspace,default_sort"`
292
+ StartsAt string `json:"starts_at" table:"starts at"`
293
+ StartsNext string `json:"starts_next" table:"starts next"`
294
+ StopsAfter string `json:"stops_after" table:"stops after"`
295
+ StopsNext string `json:"stops_next" table:"stops next"`
296
+ }
297
+
298
+ func scheduleListRowFromWorkspace (now time.Time , workspace codersdk.Workspace ) scheduleListRow {
299
+ autostartDisplay := ""
300
+ nextStartDisplay := ""
257
301
if ! ptr .NilOrEmpty (workspace .AutostartSchedule ) {
258
- sched , err := cron .Weekly (ptr .NilToEmpty (workspace .AutostartSchedule ))
259
- if err != nil {
260
- // This should never happen.
261
- _ , _ = fmt .Fprintf (out , "Invalid autostart schedule %q for workspace %s: %s\n " , * workspace .AutostartSchedule , workspace .Name , err .Error ())
262
- return nil
302
+ if sched , err := cron .Weekly (* workspace .AutostartSchedule ); err == nil {
303
+ autostartDisplay = fmt .Sprintf ("%s %s (%s)" , sched .Time (), sched .DaysOfWeek (), sched .Location ())
304
+ nextStartDisplay = timeDisplay (sched .Next (now ))
263
305
}
264
- schedNext := sched .Next (time .Now ()).In (sched .Location ())
265
- schedStart = fmt .Sprintf ("%s %s (%s)" , sched .Time (), sched .DaysOfWeek (), sched .Location ())
266
- schedNextStart = schedNext .Format (timeFormat + " on " + dateFormat )
267
306
}
268
307
308
+ autostopDisplay := ""
309
+ nextStopDisplay := ""
269
310
if ! ptr .NilOrZero (workspace .TTLMillis ) {
270
- d := time .Duration (* workspace .TTLMillis ) * time .Millisecond
271
- schedStop = durationDisplay (d ) + " after start"
272
- }
273
-
274
- if ! workspace .LatestBuild .Deadline .IsZero () {
275
- if workspace .LatestBuild .Transition != "start" {
276
- schedNextStop = "-"
277
- } else {
278
- schedNextStop = workspace .LatestBuild .Deadline .Time .In (loc ).Format (timeFormat + " on " + dateFormat )
279
- schedNextStop = fmt .Sprintf ("%s (in %s)" , schedNextStop , durationDisplay (time .Until (workspace .LatestBuild .Deadline .Time )))
311
+ dur := time .Duration (* workspace .TTLMillis ) * time .Millisecond
312
+ autostopDisplay = durationDisplay (dur )
313
+ if ! workspace .LatestBuild .Deadline .IsZero () && workspace .LatestBuild .Transition == codersdk .WorkspaceTransitionStart {
314
+ nextStopDisplay = timeDisplay (workspace .LatestBuild .Deadline .Time )
280
315
}
281
316
}
282
-
283
- tw := cliui .Table ()
284
- tw .AppendRow (table.Row {"Starts at" , schedStart })
285
- tw .AppendRow (table.Row {"Starts next" , schedNextStart })
286
- tw .AppendRow (table.Row {"Stops at" , schedStop })
287
- tw .AppendRow (table.Row {"Stops next" , schedNextStop })
288
-
289
- _ , _ = fmt .Fprintln (out , tw .Render ())
290
- return nil
317
+ return scheduleListRow {
318
+ WorkspaceName : workspace .Name ,
319
+ StartsAt : autostartDisplay ,
320
+ StartsNext : nextStartDisplay ,
321
+ StopsAfter : autostopDisplay ,
322
+ StopsNext : nextStopDisplay ,
323
+ }
291
324
}
0 commit comments