Skip to content

Commit 14ae6b8

Browse files
committed
[coconut] Update to current API
New coloring and tree/table drawing. Improved: env create env show env list env control Added: role query task list Removed: role list
1 parent b7a019a commit 14ae6b8

7 files changed

Lines changed: 332 additions & 54 deletions

File tree

coconut/cmd/environment_create.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,6 @@ creation of a new O² environment.`, product.PRETTY_SHORTNAME),
4545
func init() {
4646
environmentCmd.AddCommand(environmentCreateCmd)
4747

48-
environmentCreateCmd.Flags().StringP("workflow", "w", "", "workflow to be loaded in the new environment")
49-
environmentCreateCmd.MarkFlagRequired("workflow")
48+
environmentCreateCmd.Flags().StringP("workflow-template", "w", "", "workflow to be loaded in the new environment")
49+
environmentCreateCmd.MarkFlagRequired("workflow-template")
5050
}

coconut/cmd/environment_show.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,7 @@ details of an existing O² environment.`, product.PRETTY_SHORTNAME),
4545

4646
func init() {
4747
environmentCmd.AddCommand(environmentShowCmd)
48+
49+
environmentShowCmd.Flags().BoolP("tasks", "t", false, "print a list of tasks in this environment")
50+
environmentShowCmd.Flags().BoolP("workflow", "w", false, "print the workflow tree")
4851
}

coconut/cmd/role_query.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* === This file is part of ALICE O² ===
3+
*
4+
* Copyright 2018 CERN and copyright holders of ALICE O².
5+
* Author: Teo Mrnjavac <teo.mrnjavac@cern.ch>
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*
20+
* In applying this license CERN does not waive the privileges and
21+
* immunities granted to it by virtue of its status as an
22+
* Intergovernmental Organization or submit itself to any jurisdiction.
23+
*/
24+
25+
package cmd
26+
27+
import (
28+
"github.com/spf13/cobra"
29+
"github.com/AliceO2Group/Control/coconut/control"
30+
)
31+
32+
// roleQueryCmd represents the role list command
33+
var roleQueryCmd = &cobra.Command{
34+
Use: "query [environment id] [query path]",
35+
Aliases: []string{"query", "q"},
36+
Short: "query O² roles",
37+
Long: `The role query command returns one or more role trees.`,
38+
Run: control.WrapCall(control.QueryRoles),
39+
Args: cobra.ExactArgs(2),
40+
}
41+
42+
func init() {
43+
roleCmd.AddCommand(roleQueryCmd)
44+
}

coconut/cmd/task.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* === This file is part of ALICE O² ===
3+
*
4+
* Copyright 2018 CERN and copyright holders of ALICE O².
5+
* Author: Teo Mrnjavac <teo.mrnjavac@cern.ch>
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
*
20+
* In applying this license CERN does not waive the privileges and
21+
* immunities granted to it by virtue of its status as an
22+
* Intergovernmental Organization or submit itself to any jurisdiction.
23+
*/
24+
25+
package cmd
26+
27+
import (
28+
"fmt"
29+
30+
"github.com/AliceO2Group/Control/common/product"
31+
"github.com/spf13/cobra"
32+
)
33+
34+
// taskCmd represents the task command
35+
var taskCmd = &cobra.Command{
36+
Use: "task",
37+
Aliases: []string{"t"},
38+
Short: "query the status of O² tasks",
39+
Long: fmt.Sprintf(`The task command queries the running instance of %s to
40+
display information on active O² tasks.`, product.PRETTY_SHORTNAME),
41+
}
42+
43+
func init() {
44+
rootCmd.AddCommand(taskCmd)
45+
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@ import (
2929
"github.com/AliceO2Group/Control/coconut/control"
3030
)
3131

32-
// roleListCmd represents the role list command
33-
var roleListCmd = &cobra.Command{
32+
// taskListCmd represents the task list command
33+
var taskListCmd = &cobra.Command{
3434
Use: "list",
3535
Aliases: []string{"list", "ls", "l"},
36-
Short: "list O² roles",
37-
Long: `The role list command shows a list of currently active roles.
38-
This includes O² roles in any state.`,
36+
Short: "list O² tasks",
37+
Long: `The task list command shows a list of currently active tasks.
38+
This includes O² tasks in any state.`,
3939
Run: control.WrapCall(control.GetTasks),
4040
}
4141

4242
func init() {
43-
roleCmd.AddCommand(roleListCmd)
43+
taskCmd.AddCommand(taskListCmd)
4444
}

coconut/control/control.go

Lines changed: 100 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,29 @@
2727
package control
2828

2929
import (
30-
"github.com/AliceO2Group/Control/common/product"
31-
"github.com/spf13/cobra"
3230
"context"
33-
"github.com/spf13/viper"
34-
"github.com/briandowns/spinner"
31+
"errors"
32+
"fmt"
33+
"io"
34+
"os"
35+
"strconv"
36+
"strings"
3537
"time"
38+
3639
"github.com/AliceO2Group/Control/coconut"
3740
"github.com/AliceO2Group/Control/coconut/protos"
38-
"google.golang.org/grpc"
39-
"io"
40-
"github.com/sirupsen/logrus"
41-
"os"
4241
"github.com/AliceO2Group/Control/common/logger"
42+
"github.com/AliceO2Group/Control/common/product"
43+
"github.com/briandowns/spinner"
4344
"github.com/olekukonko/tablewriter"
44-
"fmt"
45-
"strings"
46-
"strconv"
47-
"errors"
45+
"github.com/sirupsen/logrus"
46+
"github.com/spf13/cobra"
47+
"github.com/spf13/viper"
48+
"google.golang.org/grpc"
4849
)
4950

5051
const(
51-
CALL_TIMEOUT = 20*time.Second
52+
CALL_TIMEOUT = 55*time.Second
5253
SPINNER_TICK = 100*time.Millisecond
5354
)
5455

@@ -139,7 +140,7 @@ func GetEnvironments(cxt context.Context, rpc *coconut.RpcClient, cmd *cobra.Com
139140
data := make([][]string, 0, 0)
140141
for _, envi := range response.GetEnvironments() {
141142
formatted := formatTimestamp(envi.GetCreatedWhen())
142-
data = append(data, []string{envi.GetId(), formatted, envi.GetState()})
143+
data = append(data, []string{envi.GetId(), formatted, colorState(envi.GetState())})
143144
}
144145

145146
table.AppendBulk(data)
@@ -151,7 +152,7 @@ func GetEnvironments(cxt context.Context, rpc *coconut.RpcClient, cmd *cobra.Com
151152

152153

153154
func CreateEnvironment(cxt context.Context, rpc *coconut.RpcClient, cmd *cobra.Command, args []string, o io.Writer) (err error) {
154-
wfPath, err := cmd.Flags().GetString("workflow")
155+
wfPath, err := cmd.Flags().GetString("workflow-template")
155156
if err != nil {
156157
return
157158
}
@@ -161,14 +162,17 @@ func CreateEnvironment(cxt context.Context, rpc *coconut.RpcClient, cmd *cobra.C
161162
}
162163

163164
var response *pb.NewEnvironmentReply
164-
response, err = rpc.NewEnvironment(cxt, &pb.NewEnvironmentRequest{Workflow: wfPath}, grpc.EmptyCallOption{})
165+
response, err = rpc.NewEnvironment(cxt, &pb.NewEnvironmentRequest{WorkflowTemplate: wfPath}, grpc.EmptyCallOption{})
165166
if err != nil {
166167
return
167168
}
168169

169-
fmt.Fprintln(o, "new environment created")
170-
fmt.Fprintf(o, "environment id: %s\n", response.GetId())
171-
fmt.Fprintf(o, "state: %s\n", response.GetState())
170+
env := response.GetEnvironment()
171+
tasks := env.GetTasks()
172+
fmt.Fprintf(o, "new environment created with %s tasks\n", blue(len(tasks)))
173+
fmt.Fprintf(o, "environment id: %s\n", grey(env.GetId()))
174+
fmt.Fprintf(o, "state: %s\n", colorState(env.GetState()))
175+
fmt.Fprintf(o, "root role: %s\n", env.GetRootRole())
172176

173177
return
174178
}
@@ -180,16 +184,44 @@ func ShowEnvironment(cxt context.Context, rpc *coconut.RpcClient, cmd *cobra.Com
180184
return
181185
}
182186

187+
printTasks, err := cmd.Flags().GetBool("tasks")
188+
if err != nil {
189+
return
190+
}
191+
printWorkflow, err := cmd.Flags().GetBool("workflow")
192+
if err != nil {
193+
return
194+
}
195+
183196
response, err := rpc.GetEnvironment(cxt, &pb.GetEnvironmentRequest{Id: args[0]}, grpc.EmptyCallOption{})
184197
if err != nil {
185198
return
186199
}
187200

188-
fmt.Fprintf(o, "environment id: %s\n", response.GetEnvironment().GetId())
189-
fmt.Fprintf(o, "created: %s\n", formatTimestamp(response.GetEnvironment().GetCreatedWhen()))
190-
fmt.Fprintf(o, "state: %s\n", response.GetEnvironment().GetState())
191-
fmt.Fprintf(o, "tasks: %s\n", strings.Join(response.GetEnvironment().GetTasks(), ", "))
201+
env := response.GetEnvironment()
202+
tasks := env.GetTasks()
203+
fmt.Fprintf(o, "environment id: %s\n", env.GetId())
204+
fmt.Fprintf(o, "created: %s\n", formatTimestamp(env.GetCreatedWhen()))
205+
fmt.Fprintf(o, "state: %s\n", colorState(env.GetState()))
206+
207+
if printTasks {
208+
fmt.Fprintln(o, "")
209+
drawTableShortTaskInfos(tasks,
210+
[]string{fmt.Sprintf("task id (%d tasks)", len(tasks)), "class name", "hostname", "status", "state"},
211+
func(t *pb.ShortTaskInfo) []string {
212+
return []string{
213+
t.GetTaskId(),
214+
t.GetClassName(),
215+
t.GetDeploymentInfo().GetHostname(),
216+
t.GetStatus(),
217+
colorState(t.GetState())}
218+
}, o)
219+
}
192220

221+
if printWorkflow {
222+
fmt.Fprintf(o, "\nworkflow:\n")
223+
drawWorkflow(response.GetWorkflow(), o)
224+
}
193225
return
194226
}
195227

@@ -208,11 +240,12 @@ func ControlEnvironment(cxt context.Context, rpc *coconut.RpcClient, cmd *cobra.
208240
response, err := rpc.ControlEnvironment(cxt, &pb.ControlEnvironmentRequest{Id: args[0], Type: pb.ControlEnvironmentRequest_Optype(pb.ControlEnvironmentRequest_Optype_value[event])}, grpc.EmptyCallOption{})
209241
if err != nil {
210242
return
243+
211244
}
212245

213246
fmt.Fprintln(o, "transition complete")
214247
fmt.Fprintf(o, "environment id: %s\n", response.GetId())
215-
fmt.Fprintf(o, "state: %s\n", response.GetState())
248+
fmt.Fprintf(o, "state: %s\n", colorState(response.GetState()))
216249
return
217250
}
218251

@@ -337,35 +370,56 @@ func GetTasks(cxt context.Context, rpc *coconut.RpcClient, cmd *cobra.Command, a
337370
return
338371
}
339372

340-
if len(response.GetTasks()) == 0 {
373+
tasks := response.GetTasks()
374+
375+
if len(tasks) == 0 {
341376
fmt.Fprintln(o, "no tasks running")
342377
} else {
343-
table := tablewriter.NewWriter(o)
344-
table.SetHeader([]string{"name", "hostname", "locked"})
345-
table.SetBorder(false)
346-
fg := tablewriter.Colors{tablewriter.Bold, tablewriter.FgYellowColor}
347-
table.SetHeaderColor(fg, fg, fg)
348-
349-
data := make([][]string, 0, 0)
350-
for _, taski := range response.GetTasks() {
351-
data = append(data, []string{taski.GetName(), taski.GetHostname(), strconv.FormatBool(taski.GetLocked())})
352-
}
353-
354-
table.AppendBulk(data)
355-
table.Render()
378+
drawTableShortTaskInfos(tasks,
379+
[]string{fmt.Sprintf("task id (%d tasks)", len(tasks)), "class name", "hostname", "locked", "status", "state"},
380+
func(t *pb.ShortTaskInfo) []string {
381+
return []string{
382+
t.GetTaskId(),
383+
t.GetClassName(),
384+
t.GetDeploymentInfo().GetHostname(),
385+
strconv.FormatBool(t.GetLocked()),
386+
t.GetStatus(),
387+
colorState(t.GetState())}
388+
}, o)
356389
}
357390

358391
return nil
359392
}
360393

361394

362-
func formatTimestamp(rfc3339timestamp string) string {
363-
timestamp, err := time.Parse(time.RFC3339, rfc3339timestamp)
364-
var formatted string
365-
if err == nil {
366-
formatted = timestamp.Local().Format("2006-01-02 15:04:05 MST")
395+
func QueryRoles(cxt context.Context, rpc *coconut.RpcClient, cmd *cobra.Command, args []string, o io.Writer) (err error) {
396+
if len(args) != 2 {
397+
err = errors.New(fmt.Sprintf("accepts 2 arg(s), received %d", len(args)))
398+
return
399+
}
400+
envId := args[0]
401+
queryPath := args[1]
402+
403+
response, err := rpc.GetRoles(cxt, &pb.GetRolesRequest{EnvId: envId, PathSpec: queryPath}, grpc.EmptyCallOption{})
404+
if err != nil {
405+
return
406+
}
407+
408+
roots := response.GetRoles()
409+
410+
if len(roots) == 0 {
411+
fmt.Fprintln(o, "no roles found")
367412
} else {
368-
formatted = "unknown"
413+
for i, root := range roots {
414+
fmt.Fprintf(o, "(%s)\n", yellow(i))
415+
fmt.Fprintf(o, "role path: %s\n", root.GetFullPath())
416+
fmt.Fprintf(o, "status: %s\n", root.GetStatus())
417+
fmt.Fprintf(o, "state: %s\n", root.GetState())
418+
419+
fmt.Fprintf(o, "subtree:\n")
420+
drawWorkflow(root, o)
421+
}
369422
}
370-
return formatted
371-
}
423+
424+
return nil
425+
}

0 commit comments

Comments
 (0)