diff --git a/index.html b/index.html
index 9fb7032..4df3d9f 100644
--- a/index.html
+++ b/index.html
@@ -29,6 +29,7 @@
diff --git a/script.js b/script.js
index 9d04c45..b4f4f42 100644
--- a/script.js
+++ b/script.js
@@ -33,26 +33,53 @@ var controllers = [];
var uses = {};
var groups = {};
+var instance;
+var timeoutFunction;
+var repainting = false;
-var insertByName = function(index, value) {
+var insertByNameOrType = function(index, value) {
if (!value || !value.metadata.labels || !value.metadata.name) {
return;
}
- // console.log("type = " + value.type + " labels = " + value.metadata.name);
- // var list = groups[value.metadata.name];
- var key = value.metadata.labels.name;
- var list = groups[key];
- if (!list) {
+ var key = getNodeKey(value);
+ addGroupName(key);
+ if (!isVisibleGroup(key)){
+ return;
+ }
+ var list = groups[key];
+ if (!list) {
list = [];
groups[key] = list;
- }
- list.push(value);
+ }
+ list.push(value);
};
-var groupByName = function() {
- $.each(pods.items, insertByName);
- $.each(controllers.items, insertByName);
- $.each(services.items, insertByName);
+function isVisibleGroup(key){
+ if ($("input#"+key).length != 0 && $("input#"+key).prop("checked") ){
+ return true;
+ }
+ return false;
+}
+
+function clearGroupNames(){
+ $("group-names").clear();
+}
+
+
+function addGroupName(groupName){
+ if ($("input#"+groupName).length == 0){
+ $("#group-names").append("
"+groupName+"");
+ }
+}
+
+function getNodeKey(itemNode){
+ return (itemNode.metadata.labels.type ? itemNode.metadata.labels.type : itemNode.metadata.labels.name);
+}
+
+var groupByNameOrType = function() {
+ $.each(pods.items, insertByNameOrType);
+ $.each(controllers.items, insertByNameOrType);
+ $.each(services.items, insertByNameOrType);
};
var matchesLabelQuery = function(labels, selector) {
@@ -69,15 +96,15 @@ var connectControllers = function() {
connectUses();
for (var i = 0; i < controllers.items.length; i++) {
var controller = controllers.items[i];
- //console.log("controller: " + controller.metadata.name)
+ //console.log("controller: " + controller.metadata.name)
for (var j = 0; j < pods.items.length; j++) {
var pod = pods.items[j];
- if (pod.metadata.labels.name == controller.metadata.labels.name) {
- if (controller.metadata.labels.version && pod.metadata.labels.version && (controller.metadata.labels.version != pod.metadata.labels.version)) {
- continue;
- }
- //console.log('connect controller: ' + 'controller-' + controller.metadata.name + ' to pod-' + pod.metadata.name);
- jsPlumb.connect({
+ if (isVisibleGroup(getNodeKey(pod)) && getNodeKey(pod) == getNodeKey(controller)) {
+ if (controller.metadata.labels.version && pod.metadata.labels.version && (controller.metadata.labels.version != pod.metadata.labels.version)) {
+ continue;
+ }
+ //console.log('connect controller: ' + 'controller-' + controller.metadata.name + ' to pod-' + pod.metadata.name);
+ instance.connect({
source: 'controller-' + controller.metadata.name,
target: 'pod-' + pod.metadata.name,
anchors:["Bottom", "Bottom"],
@@ -90,12 +117,11 @@ var connectControllers = function() {
}
for (var i = 0; i < services.items.length; i++) {
var service = services.items[i];
- // if (service.metadata.name == 'kubernetes' || service.metadata.name == 'skydns' || service.metadata.name == 'kubernetes-ro') { continue; }
for (var j = 0; j < pods.items.length; j++) {
var pod = pods.items[j];
- //console.log('connect service: ' + 'service-' + service.metadata.name + ' to pod-' + pod.metadata.name);
- if (matchesLabelQuery(pod.metadata.labels, service.spec.selector)) {
- jsPlumb.connect(
+ //console.log('connect service: ' + 'service-' + service.metadata.name + ' to pod-' + pod.metadata.name);
+ if (isVisibleGroup(getNodeKey(pod)) && matchesLabelQuery(pod.metadata.labels, service.spec.selector)) {
+ instance.connect(
{
source: 'service-' + service.metadata.name,
target: 'pod-' + pod.metadata.name,
@@ -128,20 +154,21 @@ var connectUses = function() {
colorIx++;
if (colorIx >= colors.length) { colorIx = 0;};
$.each(pods.items, function(i, pod) {
- var podKey = pod.metadata.labels.name;
- //console.log('connect uses key: ' +key + ', ' + podKey);
+ var podKey = getNodeKey(pod);
+ //console.log('connect uses key: ' +key + ', ' + podKey);
if (podKey == key) {
$.each(list, function(j, serviceId) {
- //console.log('connect: ' + 'pod-' + pod.metadata.name + ' to service-' + serviceId);
- jsPlumb.connect(
+ //console.log('connect: ' + 'pod-' + pod.metadata.name + ' to service-' + serviceId);
+ if ( ($('#service-' + serviceId).length != 0) && ($('#pod-' + pod.metadata.name).length != 0) ){
+ instance.connect(
{
- source: 'pod-' + pod.metadata.name,
+ source: 'pod-' + pod.metadata.name,
target: 'service-' + serviceId,
endpoint: "Blank",
//anchors:["Bottom", "Top"],
- anchors:[[ 0.5, 1, 0, 1, -30, 0 ], "Top"],
+ anchors:[[ 0.5, 1, 0, 1, -30, 0 ], "Top"],
//connector: "Straight",
- connector: ["Bezier", { curviness:75 }],
+ connector: ["Bezier", { curviness:75 }],
paintStyle:{lineWidth:2,strokeStyle:color},
overlays:[
[ "Arrow", { width:15, length:30, location: 0.3}],
@@ -149,6 +176,12 @@ var connectUses = function() {
[ "Arrow", { width:15, length:30, location: 1}],
],
});
+
+
+
+ }else{
+ console.log('Could not connect: ' + 'pod-' + pod.metadata.name + ' to service-' + serviceId + " Are you using meta.label.name of the service as the uses label?");
+ }
});
}
});
@@ -163,7 +196,7 @@ var makeGroupOrder = function() {
groupScores[key] = 0;
}
if (uses[key]) {
- value = uses[key];
+ value = uses[key];
$.each(value, function(ix, uses_label) {
if (!groupScores[uses_label]) {
groupScores[uses_label] = 1;
@@ -171,6 +204,7 @@ var makeGroupOrder = function() {
groupScores[uses_label]++;
}
});
+ groupScores[key]++;
} else {
if (!groupScores["no-service"]) {
groupScores["no-service"] = 1;
@@ -179,102 +213,95 @@ var makeGroupOrder = function() {
}
}
});
+
var groupOrder = [];
$.each(groupScores, function(key, value) {
groupOrder.push(key);
- });
+ });
+
groupOrder.sort(function(a, b) { return groupScores[a] - groupScores[b]; });
-
- //console.log(groupOrder);
return groupOrder;
};
var renderNodes = function() {
- var y = 25;
- var x = 100;
- $.each(nodes.items, function(index, value) {
- console.log(value);
+
+ $.each(nodes.items, function(index, value) {
+ console.log(value);
var div = $('
');
- var ready = 'not_ready';
- $.each(value.status.conditions, function(index, condition) {
- if (condition.type === 'Ready') {
- ready = (condition.status === 'True' ? 'ready' : 'not_ready' )
- }
- });
+ var ready = isComponentReady(value);
- var eltDiv = $('
');
- eltDiv.html('
Node
' +
- truncate(value.metadata.name, 6) +
- '');
- div.append(eltDiv);
+ var eltDiv = $('
' );
+ eltDiv.html('
Node
' + truncate(value.metadata.name, 6) + '');
+
+ div.append(eltDiv);
- var elt = $('.nodesbar');
+ var elt = $('.nodesbar');
elt.append(div);
-
- x += 120;
- });
+ });
+
}
var renderGroups = function() {
+
var elt = $('#sheet');
- var y = 10;
- var serviceLeft = 0;
var groupOrder = makeGroupOrder();
- var counts = {}
+ var counts = {}
+
$.each(groupOrder, function(ix, key) {
list = groups[key];
// list = value;
- if (!list) {
- return;
- }
- var div = $('
');
- var x = 100;
+ if (!list) {
+ return;
+ }
+
+ var div = $('
');
+ var services = $('
');
+ var pods = $('
');
+ var controllers= $('
');
+
+ div.append(services);
+ div.append(pods);
+ div.append(controllers);
+
$.each(list, function(index, value) {
- //console.log("render groups: " + value.type + ", " + value.metadata.name + ", " + index)
+ //console.log("render groups: " + value.type + ", " + value.metadata.name + ", " + index)
var eltDiv = null;
- console.log(value);
- var phase = value.status.phase ? value.status.phase.toLowerCase() : '';
+ console.log(value);
+ var phase = value.status.phase ? value.status.phase.toLowerCase() : '';
+
if (value.type == "pod") {
- if ('deletionTimestamp' in value.metadata) {
- phase = 'terminating';
- }
- eltDiv = $('
');
+ var status = phase;
+ if (status == 'running'){
+ status = isComponentReady(value);
+ }else if ('deletionTimestamp' in value.metadata) {
+ status = 'terminating';
+ }
+
+ eltDiv = $('
');
eltDiv.html('
' +
- truncate(value.metadata.name, 8, true) +
- (value.metadata.labels.version ? "
" + value.metadata.labels.version : "") + "
" +
- "(" + (value.spec.nodeName ? truncate(value.spec.nodeName, 6) : "None") +")" +
- '');
+ truncate(value.metadata.name, 8, true) +
+ (value.metadata.labels.version ? "
" + value.metadata.labels.version : "") + "
" +
+ "(" + (value.spec.nodeName ? truncate(value.spec.nodeName, 6) : "None") +")" +
+ '');
+ pods.append(eltDiv);
} else if (value.type == "service") {
- eltDiv = $('
');
+ eltDiv = $('
');
eltDiv.html('
' +
- value.metadata.name +
- (value.metadata.labels.version ? "
" + value.metadata.labels.version : "") +
- (value.spec.clusterIP ? "
" + value.spec.clusterIP : "") +
- (value.status.loadBalancer && value.status.loadBalancer.ingress ? "
" + value.status.loadBalancer.ingress[0].ip + "" : "") +
- '');
+ value.metadata.name +
+ (value.metadata.labels.version ? "
" + value.metadata.labels.version : "") +
+ (value.spec.clusterIP ? "
" + value.spec.clusterIP : "") +
+ (value.status.loadBalancer && value.status.loadBalancer.ingress ? "
" + value.status.loadBalancer.ingress[0].ip + "" : "") +
+ '');
+ services.append(eltDiv);
} else {
- var key = 'controller-' + value.metadata.labels.name;
- counts[key] = key in counts ? counts[key] + 1 : 0;
- //eltDiv = $('
');
- var minLeft = 900;
- var calcLeft = 400 + (value.status.replicas * 130);
- var left = minLeft > calcLeft ? minLeft : calcLeft;
- eltDiv = $('
');
- eltDiv.html('
' +
- value.metadata.name +
- (value.metadata.labels.version ? "
" + value.metadata.labels.version : "") +
- '');
+ eltDiv = $('
');
+ eltDiv.html('
' + value.metadata.name +
+ (value.metadata.labels.version ? "
" + value.metadata.labels.version : "") +
+ '');
+ controllers.append(eltDiv);
}
- div.append(eltDiv);
- x += 130;
+
});
- y += 400;
- serviceLeft += 200;
elt.append(div);
});
};
@@ -293,16 +320,16 @@ var loadData = function() {
var req1 = $.getJSON("/api/v1/pods?labelSelector=visualize%3Dtrue", function( data ) {
pods = data;
$.each(data.items, function(key, val) {
- val.type = 'pod';
- if (val.metadata.labels && val.metadata.labels.uses) {
- var key = val.metadata.labels.name;
- if (!uses[key]) {
- uses[key] = val.metadata.labels.uses.split("_");
- } else {
- $.each(val.metadata.labels.uses.split("_"), function(ix, use) { insertUse(key, use); });
- }
- }
- });
+ val.type = 'pod';
+ if (val.metadata.labels && val.metadata.labels.uses) {
+ var key = getNodeKey(val);
+ if (!uses[key]) {
+ uses[key] = val.metadata.labels.uses.split("_");
+ } else {
+ $.each(val.metadata.labels.uses.split("_"), function(ix, use) { insertUse(key, use); });
+ }
+ }
+ });
});
var req2 = $.getJSON("/api/v1/replicationcontrollers?labelSelector=visualize%3Dtrue", function( data ) {
@@ -319,9 +346,9 @@ var loadData = function() {
//console.log("loadData(): Services");
//console.log(services);
$.each(data.items, function(key, val) {
- val.type = 'service';
- //console.log("service ID = " + val.metadata.name)
- });
+ val.type = 'service';
+ //console.log("service ID = " + val.metadata.name)
+ });
});
var req4 = $.getJSON("/api/v1/nodes", function( data ) {
@@ -342,36 +369,52 @@ var loadData = function() {
return deferred;
}
-function refresh(instance) {
+function refresh() {
+
+ if (repainting){
+ return;
+ }
+
pods = [];
services = [];
controllers = [];
- nodes = [];
+ nodes = [];
uses = {};
groups = {};
-
-
+
$.when(loadData()).then(function() {
- groupByName();
- $('#sheet').empty();
- renderNodes();
- renderGroups();
- connectControllers();
-
- setTimeout(function() {
- refresh(instance);
- }, 2000);
+ if (!repainting){
+ groupByNameOrType();
+ instance.reset();
+ $('.nodesbar').empty();
+ $('.group').empty();
+ $('#sheet').empty();
+ renderNodes();
+ renderGroups();
+ connectControllers();
+ }
});
}
+function isComponentReady (component){
+ var ready = 'not_ready';
+ $.each(component.status.conditions, function(index, condition) {
+ if (condition.type === 'Ready') {
+ ready = (condition.status === 'True' ? 'ready' : 'not_ready' )
+ }
+ });
+ return ready;
+}
+
jsPlumb.bind("ready", function() {
- var instance = jsPlumb.getInstance({
+
+ instance = jsPlumb.getInstance({
// default drag options
DragOptions : { cursor: 'pointer', zIndex:2000 },
// the overlays to decorate each connection with. note that the label overlay uses a function to generate the label text; in this
// case it returns the 'labelText' member that we set on each connection in the 'init' method below.
ConnectionOverlays : [
- [ "Arrow", { location:1 } ],
+ //[ "Arrow", { location:1 } ],
//[ "Label", {
// location:0.1,
// id:"label",
@@ -381,6 +424,19 @@ jsPlumb.bind("ready", function() {
Container:"flowchart-demo"
});
- refresh(instance);
- jsPlumb.fire("jsPlumbDemoLoaded", instance);
- });
+ refresh();
+ scheduleRefresh();
+});
+
+function scheduleRefresh(){
+ timeoutFunction= setInterval(function() {
+ refresh();
+ }, 3000);
+}
+
+$( window ).resize(function() {
+ repainting = true;
+ instance.repaintEverything();
+ repainting = false;
+});
+
diff --git a/style.css b/style.css
index 4198bf3..55fefbf 100644
--- a/style.css
+++ b/style.css
@@ -5,16 +5,62 @@
.service {
background-color: rgb(0,153,57);
color: white;
+ min-width: 130px;
+ min-height: 100px
+ height: 100px;
+ width: 100px;
+}
+
+.group {
+ padding: 2%;
+ display: inline;
+ float: left;
+ clear: both;
+ width: 100%;
+ min-width: 100%;
+}
+
+.services{
+ clear: both;
+ float: left;
+ display: inline;
+ position: inherit;
+ margin: 3%;
+}
+.pods{
+ clear: both;
+ float: left;
+ display: inline;
+ position: inherit;
+ width: 90%;
+ min-width: 90%;
}
+.controllers{
+ clear: both;
+ float: left;
+ display: inline;
+ position: inherit;
+ width: 90%;
+}
.controller {
background-color:rgb(51,105,232);
color: white;
+ min-width: 130px;
+ min-height: 100px
+ height: 100px;
+ width: 100px;
+ clear: none;
+ float: right !important;
}
.pod {
+ min-width: 100px;
+ min-height: 100px
+ height: 100px;
width: 100px;
background-color:#eeeeef;
+ margin: 1%;
}
.pending {
@@ -23,12 +69,16 @@
.window {
line-height: 1em;
- display: table;
+ display: inline;
+ float: left;
+ position: relative !important;
}
.window span {
display: table-cell;
vertical-align: middle;
+ float: none;
+ display: block;
}
.logo {
@@ -63,15 +113,21 @@
left: 0;
right: 0;
top: 50px;
- height: 200px;
+ height: 160px;
background-color: light-grey;
border-bottom: thick solid black;
}
.not_ready {
- background-color: red;
+ background-color: #FF7F24;
}
.terminating {
background-color: red;
}
+
+#group-names{
+ float:right;
+ padding-right:5%;
+}
+