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

Commit

Permalink
Dynamic sizing nodes (#208)
Browse files Browse the repository at this point in the history
* dynamic sizing nodes

* remove whitespaces
  • Loading branch information
tomislater authored and hjacobs committed Mar 6, 2019
1 parent c352bc4 commit 8efc01d
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 53 deletions.
7 changes: 7 additions & 0 deletions app/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export default class App {
this.clusterStatuses = new Map()
this.viewContainerTargetPosition = new PIXI.Point()
this.bootstrapping = true

this.startDrawingPodsAt = 24
this.defaultPodsPerRow = 6
this.defaultWidthOfNodePx = 105
this.defaultHeightOfNodePx = 115
this.sizeOfPodPx = 13
this.heightOfTopHandlePx = 15
}

parseLocationHash() {
Expand Down
25 changes: 13 additions & 12 deletions app/src/bars.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,41 +14,42 @@ export default class Bars extends PIXI.Graphics {
draw() {
const bars = this

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

bars.beginFill(App.current.theme.primaryColor, 0.1)
bars.drawRect(5, 110 - barHeight, 15, barHeight)
bars.drawRect(5, heightOfNodeWoPaddingPx - barHeightPx, 15, barHeightPx)
bars.endFill()

// CPU
const cpuHeight = barHeight / bars.resources.cpu.capacity
const cpuHeight = barHeightPx / bars.resources.cpu.capacity
bars.interactive = true
bars.lineStyle(0, 0xaaffaa, 1)
bars.beginFill(getBarColor(bars.resources.cpu.requested, bars.resources.cpu.capacity - bars.resources.cpu.reserved), 1)
bars.drawRect(5, 110 - (bars.resources.cpu.requested + bars.resources.cpu.reserved) * cpuHeight, 2.5, (bars.resources.cpu.requested + bars.resources.cpu.reserved) * cpuHeight)
bars.drawRect(5, heightOfNodeWoPaddingPx - (bars.resources.cpu.requested + bars.resources.cpu.reserved) * cpuHeight, 2.5, (bars.resources.cpu.requested + bars.resources.cpu.reserved) * cpuHeight)
bars.beginFill(getBarColor(bars.resources.cpu.used, bars.resources.cpu.capacity), 1)
bars.drawRect(7.5, 110 - bars.resources.cpu.used * cpuHeight, 2.5, bars.resources.cpu.used * cpuHeight)
bars.drawRect(7.5, heightOfNodeWoPaddingPx - bars.resources.cpu.used * cpuHeight, 2.5, bars.resources.cpu.used * cpuHeight)
bars.endFill()
bars.lineStyle(1, App.current.theme.primaryColor, 1)
bars.drawRect(5, 110 - bars.resources.cpu.reserved * cpuHeight, 5, bars.resources.cpu.reserved * cpuHeight)
bars.drawRect(5, heightOfNodeWoPaddingPx - bars.resources.cpu.reserved * cpuHeight, 5, bars.resources.cpu.reserved * cpuHeight)

// Memory
const scale = bars.resources.memory.capacity / barHeight
const scale = bars.resources.memory.capacity / barHeightPx
bars.lineStyle(0, 0xaaffaa, 1)
bars.beginFill(getBarColor(bars.resources.memory.requested, bars.resources.memory.capacity - bars.resources.memory.reserved), 1)
bars.drawRect(14, 110 - (bars.resources.memory.requested + bars.resources.memory.reserved) / scale, 2.5, (bars.resources.memory.requested + bars.resources.memory.reserved) / scale)
bars.drawRect(14, heightOfNodeWoPaddingPx - (bars.resources.memory.requested + bars.resources.memory.reserved) / scale, 2.5, (bars.resources.memory.requested + bars.resources.memory.reserved) / scale)
bars.beginFill(getBarColor(bars.resources.memory.used, bars.resources.memory.capacity), 1)
bars.drawRect(16.5, 110 - bars.resources.memory.used / scale, 2.5, bars.resources.memory.used / scale)
bars.drawRect(16.5, heightOfNodeWoPaddingPx - bars.resources.memory.used / scale, 2.5, bars.resources.memory.used / scale)
bars.endFill()
bars.lineStyle(1, App.current.theme.primaryColor, 1)
bars.drawRect(14, 110 - bars.resources.memory.reserved / scale, 5, bars.resources.memory.reserved / scale)
bars.drawRect(14, heightOfNodeWoPaddingPx - bars.resources.memory.reserved / scale, 5, bars.resources.memory.reserved / scale)

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

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

bars.on('mouseover', function () {
let s = 'CPU: \n'
Expand Down
47 changes: 37 additions & 10 deletions app/src/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,34 @@ export default class Cluster extends PIXI.Graphics {
let workerWidth = 0
let workerHeight = 0
const workerNodes = []
const maxWidth = window.innerWidth - 130

let maxPods = 0
// get the largest number of pods
for (const n of Object.values(this.cluster.nodes)) {
const podsInNode = Object.values(n.pods).length
if (podsInNode >= maxPods) {
maxPods = podsInNode
}
}

// with maxPods we can calculate the size of all nodes in the cluster
this.podsPerRow = Math.max(
App.current.defaultPodsPerRow,
Math.ceil(Math.sqrt(maxPods))
)

this.widthOfNodePx = Math.max(
App.current.defaultWidthOfNodePx,
Math.floor(this.podsPerRow * App.current.sizeOfPodPx + App.current.startDrawingPodsAt + 2)
)

this.heightOfNodePx = Math.max(
App.current.defaultHeightOfNodePx,
Math.floor(this.podsPerRow * App.current.sizeOfPodPx + App.current.heightOfTopHandlePx + (App.current.sizeOfPodPx * 2) + 2)
)

const maxWidth = window.innerWidth - (this.widthOfNodePx * 1.2)

for (const nodeName of Object.keys(this.cluster.nodes).sort()) {
const node = this.cluster.nodes[nodeName]
var nodeBox = new Node(node, this, this.tooltip)
Expand All @@ -47,29 +74,29 @@ export default class Cluster extends PIXI.Graphics {
if (masterX > maxWidth) {
masterWidth = masterX
masterX = left
masterY += nodeBox.height + padding
masterHeight += nodeBox.height + padding
masterY += this.heightOfNodePx + padding
masterHeight += this.heightOfNodePx + padding
}
if (masterHeight == 0) {
masterHeight = nodeBox.height + padding
masterHeight = this.heightOfNodePx + padding
}
nodeBox.x = masterX
nodeBox.y = masterY
masterX += nodeBox.width + padding
masterX += this.widthOfNodePx + padding
} else {
if (workerX > maxWidth) {
workerWidth = workerX
workerX = left
workerY += nodeBox.height + padding
workerHeight += nodeBox.height + padding
workerY += this.heightOfNodePx + padding
workerHeight += this.heightOfNodePx + padding
}
workerNodes.push(nodeBox)
if (workerHeight == 0) {
workerHeight = nodeBox.height + padding
workerHeight = this.heightOfNodePx + padding
}
nodeBox.x = workerX
nodeBox.y = workerY
workerX += nodeBox.width + padding
workerX += this.widthOfNodePx + padding
}
this.addChild(nodeBox)
}
Expand All @@ -95,7 +122,7 @@ export default class Cluster extends PIXI.Graphics {

const topHandle = this.topHandle = new PIXI.Graphics()
topHandle.beginFill(App.current.theme.primaryColor, 1)
topHandle.drawRect(0, 0, width, 15)
topHandle.drawRect(0, 0, width, App.current.heightOfTopHandlePx)
topHandle.endFill()
topHandle.interactive = true
topHandle.buttonMode = true
Expand Down
54 changes: 30 additions & 24 deletions app/src/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,19 @@ export default class Node extends PIXI.Graphics {
const nodeBox = this
const topHandle = new PIXI.Graphics()
topHandle.beginFill(App.current.theme.primaryColor, 1)
topHandle.drawRect(0, 0, 105, 15)
topHandle.drawRect(0, 0, this.cluster.widthOfNodePx, App.current.heightOfTopHandlePx)
topHandle.endFill()
const ellipsizedNodeName = this.node.name.length > 17 ? this.node.name.substring(0, 17).concat('…') : this.node.name
// there is about 2.83 letters per pod
const roomForText = Math.floor(2.83 * this.cluster.podsPerRow)
const ellipsizedNodeName = this.node.name.length > roomForText ? this.node.name.substring(0, roomForText).concat('…') : this.node.name
const text = new PIXI.Text(ellipsizedNodeName, {fontFamily: 'ShareTechMono', fontSize: 10, fill: 0x000000})
text.x = 2
text.y = 2
topHandle.addChild(text)
nodeBox.addChild(topHandle)
nodeBox.lineStyle(2, App.current.theme.primaryColor, 1)
nodeBox.beginFill(App.current.theme.secondaryColor, 1)
nodeBox.drawRect(0, 0, 105, 115)
nodeBox.drawRect(0, 0, this.cluster.widthOfNodePx, this.cluster.heightOfNodePx)
nodeBox.endFill()
nodeBox.lineStyle(2, 0xaaaaaa, 1)
topHandle.interactive = true
Expand All @@ -85,7 +87,7 @@ export default class Node extends PIXI.Graphics {
s += '\n ' + key + ': ' + nodeBox.node.labels[key]
}
nodeBox.tooltip.setText(s)
nodeBox.tooltip.position = nodeBox.toGlobal(new PIXI.Point(0, 15))
nodeBox.tooltip.position = nodeBox.toGlobal(new PIXI.Point(0, App.current.heightOfTopHandlePx))
nodeBox.tooltip.visible = true
})
topHandle.on('mouseout', function () {
Expand All @@ -103,33 +105,37 @@ export default class Node extends PIXI.Graphics {

addPods(sorterFn) {
const nodeBox = this
let px = 24
let py = 20
const px = App.current.startDrawingPodsAt
const py = App.current.heightOfTopHandlePx + 5
let podsCounter = 0
let podsKubeSystemCounter = 0
const pods = Object.values(this.node.pods).sort(sorterFn)
for (const pod of pods) {
if (pod.namespace != 'kube-system') {
const podBox = Pod.getOrCreate(pod, this.cluster, this.tooltip)
podBox.movePodTo(new PIXI.Point(px, py))
podBox.movePodTo(
new PIXI.Point(
// we have a room for this.cluster.podsPerRow pods
px + (App.current.sizeOfPodPx * (podsCounter % this.cluster.podsPerRow)),
// we just count when to get to another row
py + (App.current.sizeOfPodPx * Math.floor(podsCounter / this.cluster.podsPerRow))
)
)
nodeBox.addChild(podBox.draw())
px += 13
if (px > 90) {
px = 24
py += 13
}
}
}
px = 24
py = 100
for (const pod of pods) {
if (pod.namespace == 'kube-system') {
podsCounter++
} else {
// kube-system pods
const podBox = Pod.getOrCreate(pod, this.cluster, this.tooltip)
podBox.movePodTo(new PIXI.Point(px, py))
podBox.movePodTo(
new PIXI.Point(
// we have a room for this.cluster.podsPerRow pods
px + (App.current.sizeOfPodPx * (podsKubeSystemCounter % this.cluster.podsPerRow)),
// like above (for not kube-system pods), but we count from the bottom
this.cluster.heightOfNodePx - App.current.sizeOfPodPx - 2 - (App.current.sizeOfPodPx * Math.floor(podsKubeSystemCounter / this.cluster.podsPerRow))
)
)
nodeBox.addChild(podBox.draw())
px += 13
if (px > 90) {
px = 24
py -= 13
}
podsKubeSystemCounter++
}
}
}
Expand Down
21 changes: 14 additions & 7 deletions kube_ops_view/mock.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import time
import random
import string


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

# generate longer name for a node
suffix = ''.join(
[random.choice(string.ascii_letters) for n in range(random.randint(1, 20))]
)

node = {
'name': 'node-{}'.format(i),
'name': f'node-{i}-{suffix}',
'labels': labels,
'status': {
'capacity': {'cpu': '4', 'memory': '32Gi', 'pods': '110'},
'allocatable': {'cpu': '3800m', 'memory': '31Gi'}
'capacity': {'cpu': '8', 'memory': '64Gi', 'pods': '110'},
'allocatable': {'cpu': '7800m', 'memory': '62Gi'}
},
'pods': pods,
# get data from containers (usage)
Expand Down

0 comments on commit 8efc01d

Please sign in to comment.