Skip to content

Commit 723483f

Browse files
committed
hack/cluster-version-util/task_graph: Task-node granularity
Make it easier to think about task-nodes as opaque objects by assigning them runlevel and component properties, and using that information to label names in the rendered graph.
1 parent a7d6e43 commit 723483f

File tree

2 files changed

+84
-24
lines changed

2 files changed

+84
-24
lines changed

hack/cluster-version-util/task_graph.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import (
1212

1313
var (
1414
taskGraphOpts struct {
15-
parallel string
15+
parallel string
16+
granularity string
1617
}
1718
)
1819

@@ -24,7 +25,8 @@ func newTaskGraphCmd() *cobra.Command {
2425
RunE: runTaskGraphCmd,
2526
}
2627

27-
cmd.Flags().StringVar(&taskGraphOpts.parallel, "parallel", "by-number-and-component", "The output directory where the manifests will be rendered.")
28+
cmd.Flags().StringVar(&taskGraphOpts.parallel, "parallel", "by-number-and-component", "The parallelization strategy to use (by-number-and-component (default), flatten-by-number-and-component, or permute-flatten-by-number-and-component).")
29+
cmd.Flags().StringVar(&taskGraphOpts.granularity, "granularity", "task-node", "The output granularity to use (task-node (default) or manifest).")
2830
return cmd
2931
}
3032

@@ -59,7 +61,7 @@ func runTaskGraphCmd(cmd *cobra.Command, args []string) error {
5961
return fmt.Errorf("unrecognized parallel strategy %q", taskGraphOpts.parallel)
6062
}
6163

62-
fmt.Println(graph.Tree())
64+
fmt.Println(graph.Tree(taskGraphOpts.granularity))
6365

6466
return nil
6567
}

pkg/payload/task_graph.go

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"math/rand"
77
"regexp"
8+
"strconv"
89
"strings"
910
"sync"
1011

@@ -45,7 +46,6 @@ func ByNumberAndComponent(tasks []*Task) [][]*TaskNode {
4546
}
4647

4748
var buckets [][]*TaskNode
48-
var lastNode *TaskNode
4949
for i := 0; i < count; {
5050
matchBase := matches[i]
5151
j := i + 1
@@ -56,26 +56,45 @@ func ByNumberAndComponent(tasks []*Task) [][]*TaskNode {
5656
break
5757
}
5858
if matchBase[groupComponent] != matchNext[groupComponent] {
59-
groups = append(groups, &TaskNode{Tasks: tasks[i:j]})
59+
node := &TaskNode{
60+
Tasks: tasks[i:j],
61+
component: matchBase[groupComponent],
62+
}
63+
var err error
64+
if node.runlevel, err = strconv.Atoi(matchBase[groupNumber]); err != nil {
65+
panic(err)
66+
}
67+
groups = append(groups, node)
6068
i = j
6169
}
6270
matchBase = matchNext
6371
}
6472
if len(groups) > 0 {
65-
groups = append(groups, &TaskNode{Tasks: tasks[i:j]})
73+
node := &TaskNode{
74+
Tasks: tasks[i:j],
75+
component: matchBase[groupComponent],
76+
}
77+
var err error
78+
if node.runlevel, err = strconv.Atoi(matchBase[groupNumber]); err != nil {
79+
panic(err)
80+
}
81+
groups = append(groups, node)
6682
i = j
6783
buckets = append(buckets, groups)
68-
lastNode = nil
6984
continue
7085
}
71-
if lastNode == nil {
72-
lastNode = &TaskNode{Tasks: append([]*Task(nil), tasks[i:j]...)}
73-
i = j
74-
buckets = append(buckets, []*TaskNode{lastNode})
75-
continue
86+
node := &TaskNode{
87+
Tasks: append([]*Task(nil), tasks[i:j]...),
88+
}
89+
if matchBase != nil {
90+
node.component = matchBase[groupComponent]
91+
var err error
92+
if node.runlevel, err = strconv.Atoi(matchBase[groupNumber]); err != nil {
93+
panic(err)
94+
}
7695
}
77-
lastNode.Tasks = append(lastNode.Tasks, tasks[i:j]...)
7896
i = j
97+
buckets = append(buckets, []*TaskNode{node})
7998
}
8099
return buckets
81100
}
@@ -105,19 +124,39 @@ func FlattenByNumberAndComponent(tasks []*Task) [][]*TaskNode {
105124
break
106125
}
107126
if matchBase[groupComponent] != matchNext[groupComponent] {
108-
groups = append(groups, &TaskNode{Tasks: tasks[i:j]})
127+
node := &TaskNode{
128+
Tasks: tasks[i:j],
129+
component: matchBase[groupComponent],
130+
}
131+
var err error
132+
if node.runlevel, err = strconv.Atoi(matchBase[groupNumber]); err != nil {
133+
panic(err)
134+
}
135+
groups = append(groups, node)
109136
i = j
110137
}
111138
matchBase = matchNext
112139
}
113140
if len(groups) > 0 {
114-
groups = append(groups, &TaskNode{Tasks: tasks[i:j]})
141+
node := &TaskNode{
142+
Tasks: tasks[i:j],
143+
component: matchBase[groupComponent],
144+
}
145+
var err error
146+
if node.runlevel, err = strconv.Atoi(matchBase[groupNumber]); err != nil {
147+
panic(err)
148+
}
149+
groups = append(groups, node)
115150
i = j
116151
lastNode = nil
117152
continue
118153
}
119154
if lastNode == nil {
120-
lastNode = &TaskNode{Tasks: append([]*Task(nil), tasks[i:j]...)}
155+
lastNode = &TaskNode{
156+
Tasks: append([]*Task(nil), tasks[i:j]...),
157+
runlevel: -1,
158+
component: "FIXME",
159+
}
121160
i = j
122161
groups = append(groups, lastNode)
123162
continue
@@ -137,6 +176,12 @@ type TaskNode struct {
137176
Tasks []*Task
138177
// Out is a list of node indices to which there is an edge from this node (=dependents).
139178
Out []int
179+
180+
// runlevel is task's run level, extracted from the manifest filename.
181+
runlevel int
182+
183+
// component is task's component name, extracted from the manifest filename.
184+
component string
140185
}
141186

142187
func (n *TaskNode) String() string {
@@ -148,7 +193,7 @@ func (n *TaskNode) String() string {
148193
}
149194
arr = append(arr, t.Manifest.GVK.String())
150195
}
151-
return "{Tasks: " + strings.Join(arr, ", ") + "}"
196+
return fmt.Sprintf("{RunLevel: %d, Component: %q, Tasks: %s}", n.runlevel, n.component, strings.Join(arr, ", "))
152197
}
153198

154199
func (n *TaskNode) replaceIn(index, with int) {
@@ -370,21 +415,34 @@ func (g *TaskGraph) Roots() []int {
370415
}
371416

372417
// Tree renders the task graph in Graphviz DOT.
373-
func (g *TaskGraph) Tree() string {
418+
func (g *TaskGraph) Tree(granularity string) string {
374419
out := []string{
375420
"digraph tasks {",
376421
" labelloc=t;",
377422
" rankdir=TB;",
378423
}
379424
for i, node := range g.Nodes {
380-
label := make([]string, 0, len(node.Tasks))
381-
for _, task := range node.Tasks {
382-
label = append(label, strings.Replace(task.String(), "\"", "", -1))
425+
var label string
426+
if node.runlevel != 0 || node.component != "" {
427+
label = fmt.Sprintf("%02d-%s, %d manifests", node.runlevel, node.component, len(node.Tasks))
428+
} else {
429+
label = fmt.Sprintf("%d manifests", len(node.Tasks))
383430
}
384-
if len(label) == 0 {
385-
label = append(label, "no manifests")
431+
switch granularity {
432+
case "manifest":
433+
labels := make([]string, 0, len(node.Tasks))
434+
for _, task := range node.Tasks {
435+
labels = append(labels, strings.Replace(task.String(), "\"", "", -1))
436+
}
437+
if len(labels) > 0 {
438+
label = fmt.Sprintf("%s\\n%s", label, strings.Join(labels, "\\n"))
439+
}
440+
case "task-node":
441+
// nothing to append
442+
default:
443+
panic(fmt.Sprintf("unrecognized granularity %q", granularity))
386444
}
387-
out = append(out, fmt.Sprintf(" %d [ label=\"%s\" shape=\"box\" ];", i, strings.Join(label, "\\n")))
445+
out = append(out, fmt.Sprintf(" %d [ label=\"%s\" shape=\"box\" ];", i, label))
388446
}
389447
for i, node := range g.Nodes {
390448
for _, j := range node.Out {

0 commit comments

Comments
 (0)