Skip to content
This repository was archived by the owner on Oct 3, 2020. It is now read-only.

Commit 8efc01d

Browse files
tomislaterhjacobs
authored andcommitted
Dynamic sizing nodes (#208)
* dynamic sizing nodes * remove whitespaces
1 parent c352bc4 commit 8efc01d

File tree

5 files changed

+101
-53
lines changed

5 files changed

+101
-53
lines changed

app/src/app.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ export default class App {
2929
this.clusterStatuses = new Map()
3030
this.viewContainerTargetPosition = new PIXI.Point()
3131
this.bootstrapping = true
32+
33+
this.startDrawingPodsAt = 24
34+
this.defaultPodsPerRow = 6
35+
this.defaultWidthOfNodePx = 105
36+
this.defaultHeightOfNodePx = 115
37+
this.sizeOfPodPx = 13
38+
this.heightOfTopHandlePx = 15
3239
}
3340

3441
parseLocationHash() {

app/src/bars.js

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,42 @@ export default class Bars extends PIXI.Graphics {
1414
draw() {
1515
const bars = this
1616

17-
const barHeight = 92
17+
const barHeightPx = bars.entity.cluster.heightOfNodePx - (App.current.heightOfTopHandlePx + 5 + 3)
18+
const heightOfNodeWoPaddingPx = bars.entity.cluster.heightOfNodePx - 5
1819

1920
bars.beginFill(App.current.theme.primaryColor, 0.1)
20-
bars.drawRect(5, 110 - barHeight, 15, barHeight)
21+
bars.drawRect(5, heightOfNodeWoPaddingPx - barHeightPx, 15, barHeightPx)
2122
bars.endFill()
2223

2324
// CPU
24-
const cpuHeight = barHeight / bars.resources.cpu.capacity
25+
const cpuHeight = barHeightPx / bars.resources.cpu.capacity
2526
bars.interactive = true
2627
bars.lineStyle(0, 0xaaffaa, 1)
2728
bars.beginFill(getBarColor(bars.resources.cpu.requested, bars.resources.cpu.capacity - bars.resources.cpu.reserved), 1)
28-
bars.drawRect(5, 110 - (bars.resources.cpu.requested + bars.resources.cpu.reserved) * cpuHeight, 2.5, (bars.resources.cpu.requested + bars.resources.cpu.reserved) * cpuHeight)
29+
bars.drawRect(5, heightOfNodeWoPaddingPx - (bars.resources.cpu.requested + bars.resources.cpu.reserved) * cpuHeight, 2.5, (bars.resources.cpu.requested + bars.resources.cpu.reserved) * cpuHeight)
2930
bars.beginFill(getBarColor(bars.resources.cpu.used, bars.resources.cpu.capacity), 1)
30-
bars.drawRect(7.5, 110 - bars.resources.cpu.used * cpuHeight, 2.5, bars.resources.cpu.used * cpuHeight)
31+
bars.drawRect(7.5, heightOfNodeWoPaddingPx - bars.resources.cpu.used * cpuHeight, 2.5, bars.resources.cpu.used * cpuHeight)
3132
bars.endFill()
3233
bars.lineStyle(1, App.current.theme.primaryColor, 1)
33-
bars.drawRect(5, 110 - bars.resources.cpu.reserved * cpuHeight, 5, bars.resources.cpu.reserved * cpuHeight)
34+
bars.drawRect(5, heightOfNodeWoPaddingPx - bars.resources.cpu.reserved * cpuHeight, 5, bars.resources.cpu.reserved * cpuHeight)
3435

3536
// Memory
36-
const scale = bars.resources.memory.capacity / barHeight
37+
const scale = bars.resources.memory.capacity / barHeightPx
3738
bars.lineStyle(0, 0xaaffaa, 1)
3839
bars.beginFill(getBarColor(bars.resources.memory.requested, bars.resources.memory.capacity - bars.resources.memory.reserved), 1)
39-
bars.drawRect(14, 110 - (bars.resources.memory.requested + bars.resources.memory.reserved) / scale, 2.5, (bars.resources.memory.requested + bars.resources.memory.reserved) / scale)
40+
bars.drawRect(14, heightOfNodeWoPaddingPx - (bars.resources.memory.requested + bars.resources.memory.reserved) / scale, 2.5, (bars.resources.memory.requested + bars.resources.memory.reserved) / scale)
4041
bars.beginFill(getBarColor(bars.resources.memory.used, bars.resources.memory.capacity), 1)
41-
bars.drawRect(16.5, 110 - bars.resources.memory.used / scale, 2.5, bars.resources.memory.used / scale)
42+
bars.drawRect(16.5, heightOfNodeWoPaddingPx - bars.resources.memory.used / scale, 2.5, bars.resources.memory.used / scale)
4243
bars.endFill()
4344
bars.lineStyle(1, App.current.theme.primaryColor, 1)
44-
bars.drawRect(14, 110 - bars.resources.memory.reserved / scale, 5, bars.resources.memory.reserved / scale)
45+
bars.drawRect(14, heightOfNodeWoPaddingPx - bars.resources.memory.reserved / scale, 5, bars.resources.memory.reserved / scale)
4546

4647
bars.lineStyle(1, App.current.theme.primaryColor, 1)
4748
for (var i = 0; i < bars.resources.cpu.capacity; i++) {
48-
bars.drawRect(5, 110 - (i + 1) * cpuHeight, 5, cpuHeight)
49+
bars.drawRect(5, heightOfNodeWoPaddingPx - (i + 1) * cpuHeight, 5, cpuHeight)
4950
}
5051

51-
bars.drawRect(14, 110 - bars.resources.memory.capacity / scale, 5, bars.resources.memory.capacity / scale)
52+
bars.drawRect(14, heightOfNodeWoPaddingPx - bars.resources.memory.capacity / scale, 5, bars.resources.memory.capacity / scale)
5253

5354
bars.on('mouseover', function () {
5455
let s = 'CPU: \n'

app/src/cluster.js

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,34 @@ export default class Cluster extends PIXI.Graphics {
3838
let workerWidth = 0
3939
let workerHeight = 0
4040
const workerNodes = []
41-
const maxWidth = window.innerWidth - 130
41+
42+
let maxPods = 0
43+
// get the largest number of pods
44+
for (const n of Object.values(this.cluster.nodes)) {
45+
const podsInNode = Object.values(n.pods).length
46+
if (podsInNode >= maxPods) {
47+
maxPods = podsInNode
48+
}
49+
}
50+
51+
// with maxPods we can calculate the size of all nodes in the cluster
52+
this.podsPerRow = Math.max(
53+
App.current.defaultPodsPerRow,
54+
Math.ceil(Math.sqrt(maxPods))
55+
)
56+
57+
this.widthOfNodePx = Math.max(
58+
App.current.defaultWidthOfNodePx,
59+
Math.floor(this.podsPerRow * App.current.sizeOfPodPx + App.current.startDrawingPodsAt + 2)
60+
)
61+
62+
this.heightOfNodePx = Math.max(
63+
App.current.defaultHeightOfNodePx,
64+
Math.floor(this.podsPerRow * App.current.sizeOfPodPx + App.current.heightOfTopHandlePx + (App.current.sizeOfPodPx * 2) + 2)
65+
)
66+
67+
const maxWidth = window.innerWidth - (this.widthOfNodePx * 1.2)
68+
4269
for (const nodeName of Object.keys(this.cluster.nodes).sort()) {
4370
const node = this.cluster.nodes[nodeName]
4471
var nodeBox = new Node(node, this, this.tooltip)
@@ -47,29 +74,29 @@ export default class Cluster extends PIXI.Graphics {
4774
if (masterX > maxWidth) {
4875
masterWidth = masterX
4976
masterX = left
50-
masterY += nodeBox.height + padding
51-
masterHeight += nodeBox.height + padding
77+
masterY += this.heightOfNodePx + padding
78+
masterHeight += this.heightOfNodePx + padding
5279
}
5380
if (masterHeight == 0) {
54-
masterHeight = nodeBox.height + padding
81+
masterHeight = this.heightOfNodePx + padding
5582
}
5683
nodeBox.x = masterX
5784
nodeBox.y = masterY
58-
masterX += nodeBox.width + padding
85+
masterX += this.widthOfNodePx + padding
5986
} else {
6087
if (workerX > maxWidth) {
6188
workerWidth = workerX
6289
workerX = left
63-
workerY += nodeBox.height + padding
64-
workerHeight += nodeBox.height + padding
90+
workerY += this.heightOfNodePx + padding
91+
workerHeight += this.heightOfNodePx + padding
6592
}
6693
workerNodes.push(nodeBox)
6794
if (workerHeight == 0) {
68-
workerHeight = nodeBox.height + padding
95+
workerHeight = this.heightOfNodePx + padding
6996
}
7097
nodeBox.x = workerX
7198
nodeBox.y = workerY
72-
workerX += nodeBox.width + padding
99+
workerX += this.widthOfNodePx + padding
73100
}
74101
this.addChild(nodeBox)
75102
}
@@ -95,7 +122,7 @@ export default class Cluster extends PIXI.Graphics {
95122

96123
const topHandle = this.topHandle = new PIXI.Graphics()
97124
topHandle.beginFill(App.current.theme.primaryColor, 1)
98-
topHandle.drawRect(0, 0, width, 15)
125+
topHandle.drawRect(0, 0, width, App.current.heightOfTopHandlePx)
99126
topHandle.endFill()
100127
topHandle.interactive = true
101128
topHandle.buttonMode = true

app/src/node.js

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,19 @@ export default class Node extends PIXI.Graphics {
6464
const nodeBox = this
6565
const topHandle = new PIXI.Graphics()
6666
topHandle.beginFill(App.current.theme.primaryColor, 1)
67-
topHandle.drawRect(0, 0, 105, 15)
67+
topHandle.drawRect(0, 0, this.cluster.widthOfNodePx, App.current.heightOfTopHandlePx)
6868
topHandle.endFill()
69-
const ellipsizedNodeName = this.node.name.length > 17 ? this.node.name.substring(0, 17).concat('…') : this.node.name
69+
// there is about 2.83 letters per pod
70+
const roomForText = Math.floor(2.83 * this.cluster.podsPerRow)
71+
const ellipsizedNodeName = this.node.name.length > roomForText ? this.node.name.substring(0, roomForText).concat('…') : this.node.name
7072
const text = new PIXI.Text(ellipsizedNodeName, {fontFamily: 'ShareTechMono', fontSize: 10, fill: 0x000000})
7173
text.x = 2
7274
text.y = 2
7375
topHandle.addChild(text)
7476
nodeBox.addChild(topHandle)
7577
nodeBox.lineStyle(2, App.current.theme.primaryColor, 1)
7678
nodeBox.beginFill(App.current.theme.secondaryColor, 1)
77-
nodeBox.drawRect(0, 0, 105, 115)
79+
nodeBox.drawRect(0, 0, this.cluster.widthOfNodePx, this.cluster.heightOfNodePx)
7880
nodeBox.endFill()
7981
nodeBox.lineStyle(2, 0xaaaaaa, 1)
8082
topHandle.interactive = true
@@ -85,7 +87,7 @@ export default class Node extends PIXI.Graphics {
8587
s += '\n ' + key + ': ' + nodeBox.node.labels[key]
8688
}
8789
nodeBox.tooltip.setText(s)
88-
nodeBox.tooltip.position = nodeBox.toGlobal(new PIXI.Point(0, 15))
90+
nodeBox.tooltip.position = nodeBox.toGlobal(new PIXI.Point(0, App.current.heightOfTopHandlePx))
8991
nodeBox.tooltip.visible = true
9092
})
9193
topHandle.on('mouseout', function () {
@@ -103,33 +105,37 @@ export default class Node extends PIXI.Graphics {
103105

104106
addPods(sorterFn) {
105107
const nodeBox = this
106-
let px = 24
107-
let py = 20
108+
const px = App.current.startDrawingPodsAt
109+
const py = App.current.heightOfTopHandlePx + 5
110+
let podsCounter = 0
111+
let podsKubeSystemCounter = 0
108112
const pods = Object.values(this.node.pods).sort(sorterFn)
109113
for (const pod of pods) {
110114
if (pod.namespace != 'kube-system') {
111115
const podBox = Pod.getOrCreate(pod, this.cluster, this.tooltip)
112-
podBox.movePodTo(new PIXI.Point(px, py))
116+
podBox.movePodTo(
117+
new PIXI.Point(
118+
// we have a room for this.cluster.podsPerRow pods
119+
px + (App.current.sizeOfPodPx * (podsCounter % this.cluster.podsPerRow)),
120+
// we just count when to get to another row
121+
py + (App.current.sizeOfPodPx * Math.floor(podsCounter / this.cluster.podsPerRow))
122+
)
123+
)
113124
nodeBox.addChild(podBox.draw())
114-
px += 13
115-
if (px > 90) {
116-
px = 24
117-
py += 13
118-
}
119-
}
120-
}
121-
px = 24
122-
py = 100
123-
for (const pod of pods) {
124-
if (pod.namespace == 'kube-system') {
125+
podsCounter++
126+
} else {
127+
// kube-system pods
125128
const podBox = Pod.getOrCreate(pod, this.cluster, this.tooltip)
126-
podBox.movePodTo(new PIXI.Point(px, py))
129+
podBox.movePodTo(
130+
new PIXI.Point(
131+
// we have a room for this.cluster.podsPerRow pods
132+
px + (App.current.sizeOfPodPx * (podsKubeSystemCounter % this.cluster.podsPerRow)),
133+
// like above (for not kube-system pods), but we count from the bottom
134+
this.cluster.heightOfNodePx - App.current.sizeOfPodPx - 2 - (App.current.sizeOfPodPx * Math.floor(podsKubeSystemCounter / this.cluster.podsPerRow))
135+
)
136+
)
127137
nodeBox.addChild(podBox.draw())
128-
px += 13
129-
if (px > 90) {
130-
px = 24
131-
py -= 13
132-
}
138+
podsKubeSystemCounter++
133139
}
134140
}
135141
}

kube_ops_view/mock.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import time
22
import random
3+
import string
34

45

56
def hash_int(x: int):
@@ -37,10 +38,11 @@ def generate_mock_pod(index: int, i: int, j: int):
3738
containers = []
3839
for k in range(1 + j % 2):
3940
# generate "more real data"
40-
requests_cpu = random.randint(50, 100)
41-
requests_memory = random.randint(256, 512)
42-
usage_cpu = requests_cpu + random.randint(-45, 50)
43-
usage_memory = requests_memory + random.randint(-128, 128)
41+
requests_cpu = random.randint(10, 50)
42+
requests_memory = random.randint(64, 256)
43+
# with max, we defend ourselves against negative cpu/memory ;)
44+
usage_cpu = max(requests_cpu + random.randint(-30, 30), 1)
45+
usage_memory = max(requests_memory + random.randint(-64, 128), 1)
4446
container = {
4547
'name': 'myapp',
4648
'image': 'foo/bar/{}'.format(j),
@@ -107,12 +109,17 @@ def query_mock_cluster(cluster):
107109
usage_cpu += int(c["resources"]["usage"]["cpu"].split("m")[0])
108110
usage_memory += int(c["resources"]["usage"]["memory"].split("Mi")[0])
109111

112+
# generate longer name for a node
113+
suffix = ''.join(
114+
[random.choice(string.ascii_letters) for n in range(random.randint(1, 20))]
115+
)
116+
110117
node = {
111-
'name': 'node-{}'.format(i),
118+
'name': f'node-{i}-{suffix}',
112119
'labels': labels,
113120
'status': {
114-
'capacity': {'cpu': '4', 'memory': '32Gi', 'pods': '110'},
115-
'allocatable': {'cpu': '3800m', 'memory': '31Gi'}
121+
'capacity': {'cpu': '8', 'memory': '64Gi', 'pods': '110'},
122+
'allocatable': {'cpu': '7800m', 'memory': '62Gi'}
116123
},
117124
'pods': pods,
118125
# get data from containers (usage)

0 commit comments

Comments
 (0)