diff --git a/client/app/scripts/charts/node-shape-circle.js b/client/app/scripts/charts/node-shape-circle.js
index 0d4f53839..e4c32ade8 100644
--- a/client/app/scripts/charts/node-shape-circle.js
+++ b/client/app/scripts/charts/node-shape-circle.js
@@ -1,14 +1,22 @@
import React from 'react';
-export default function NodeShapeCircle({highlighted, size, color}) {
+export default function NodeShapeCircle({onlyHighlight, highlighted, size, color}) {
+ const hightlightNode = ;
+
+ if (onlyHighlight) {
+ return (
+
+ {highlighted && hightlightNode}
+
+ );
+ }
+
return (
- {highlighted &&
- }
-
-
-
-
+ {highlighted && hightlightNode}
+
+
+
);
}
diff --git a/client/app/scripts/charts/node-shape-stack.js b/client/app/scripts/charts/node-shape-stack.js
index 92df91031..9d13f87c8 100644
--- a/client/app/scripts/charts/node-shape-stack.js
+++ b/client/app/scripts/charts/node-shape-stack.js
@@ -1,29 +1,39 @@
import React from 'react';
import _ from 'lodash';
+function dissoc(obj, key) {
+ const newObj = _.clone(obj);
+ delete newObj[key];
+ return newObj;
+}
+
export default function NodeShapeStack(props) {
- const propsNoHighlight = _.clone(props);
- const Shape = props.shape;
- delete propsNoHighlight.highlighted;
+ const propsNoHighlight = dissoc(props, 'highlighted');
const propsOnlyHighlight = Object.assign({}, props, {onlyHighlight: true});
+
+ const Shape = props.shape;
+ const nodeCount = props.nodeCount;
const [dx, dy] = [0, 6];
const ds = 0.075;
const dsx = (props.size * 2 + dx) / (props.size * 2);
const dsy = (props.size * 2 + dy) / (props.size * 2);
const hls = [dsx, dsy];
+ const propsWithGrey = Object.assign({}, propsNoHighlight, {color: '#aaa', className: 'mock'});
+ const propsForIndex = i => (nodeCount < i ? propsWithGrey : propsNoHighlight);
+
return (
-
+
-
+
-
+
);
}
diff --git a/client/app/scripts/charts/nodes-chart.js b/client/app/scripts/charts/nodes-chart.js
index 7e40cff90..91030f316 100644
--- a/client/app/scripts/charts/nodes-chart.js
+++ b/client/app/scripts/charts/nodes-chart.js
@@ -150,6 +150,7 @@ export default class NodesChart extends React.Component {
id={node.get('id')}
label={node.get('label')}
pseudo={node.get('pseudo')}
+ nodeCount={node.get('nodeCount')}
subLabel={node.get('subLabel')}
rank={node.get('rank')}
selectedNodeScale={selectedNodeScale}
@@ -246,6 +247,7 @@ export default class NodesChart extends React.Component {
label: node.get('label_major'),
pseudo: node.get('pseudo'),
subLabel: node.get('label_minor'),
+ nodeCount: node.get('node_count'),
rank: node.get('rank'),
shape: node.get('shape'),
stack: node.get('stack'),
diff --git a/client/app/scripts/components/debug-toolbar.js b/client/app/scripts/components/debug-toolbar.js
index 1d11e62fe..8c5e139f2 100644
--- a/client/app/scripts/components/debug-toolbar.js
+++ b/client/app/scripts/components/debug-toolbar.js
@@ -7,15 +7,21 @@ const log = debug('scope:debug-panel');
import { receiveNodesDelta } from '../actions/app-actions';
import AppStore from '../stores/app-store';
+const SHAPES = ['circle', 'hexagon', 'square'];
+const NODE_COUNTS = [1, 2, 3];
+const STACK_VARIANTS = [true, false];
const sample = function(collection) {
return _.range(_.random(4)).map(() => _.sample(collection));
};
-const deltaAdd = function(name, adjacency = []) {
+const deltaAdd = function(name, adjacency = [], shape = 'circle', stack = false, nodeCount = 1) {
return {
'adjacency': adjacency,
'controls': {},
+ 'shape': shape,
+ 'stack': stack,
+ 'node_count': nodeCount,
'id': name,
'label_major': name,
'label_minor': 'weave-1',
@@ -26,6 +32,23 @@ const deltaAdd = function(name, adjacency = []) {
};
};
+function addAllVariants() {
+ const newNodes = _.flattenDeep(SHAPES.map(s => {
+ return STACK_VARIANTS.map(stack => {
+ if (!stack) return [deltaAdd([s, 1, stack].join('-'), [], s, stack, 1)];
+ return NODE_COUNTS.map(n => {
+ return deltaAdd([s, n, stack].join('-'), [], s, stack, n);
+ });
+ });
+ }));
+
+ console.log(newNodes);
+
+ receiveNodesDelta({
+ add: newNodes
+ });
+}
+
function addNodes(n) {
const ns = AppStore.getNodes();
const nodeNames = ns.keySeq().toJS();
@@ -33,7 +56,11 @@ function addNodes(n) {
const allNodes = _(nodeNames).concat(newNodeNames).value();
receiveNodesDelta({
- add: newNodeNames.map((name) => deltaAdd(name, sample(allNodes)))
+ add: newNodeNames.map((name) => deltaAdd(name,
+ sample(allNodes)),
+ _.sample(SHAPES),
+ _.sample(STACK_VARIANTS),
+ _.sample(NODE_COUNTS))
});
}
@@ -65,6 +92,7 @@ export class DebugToolbar extends React.Component {
+
);
}
diff --git a/client/app/scripts/stores/app-store.js b/client/app/scripts/stores/app-store.js
index 6471ebccc..fa6b4036d 100644
--- a/client/app/scripts/stores/app-store.js
+++ b/client/app/scripts/stores/app-store.js
@@ -39,6 +39,7 @@ function makeNode(node) {
id: node.id,
label_major: node.label_major,
label_minor: node.label_minor,
+ node_count: node.node_count,
rank: node.rank,
pseudo: node.pseudo,
stack: node.stack,
diff --git a/render/expected/expected.go b/render/expected/expected.go
index b06079e7b..da27bcfeb 100644
--- a/render/expected/expected.go
+++ b/render/expected/expected.go
@@ -131,6 +131,7 @@ var (
Pseudo: false,
Shape: square,
Stack: true,
+ NodeCount: 2,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -149,6 +150,7 @@ var (
Pseudo: false,
Shape: square,
Stack: true,
+ NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
),
@@ -166,6 +168,7 @@ var (
Pseudo: false,
Shape: square,
Stack: true,
+ NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.NonContainerProcessNodeID],
),
@@ -245,6 +248,7 @@ var (
Pseudo: false,
Shape: hexagon,
Stack: true,
+ NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -264,6 +268,7 @@ var (
Pseudo: false,
Shape: hexagon,
Stack: true,
+ NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
fixture.Report.Container.Nodes[fixture.ServerContainerNodeID],
@@ -375,6 +380,7 @@ var (
Rank: "ping/pong-a",
Pseudo: false,
Shape: pentagon,
+ NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
@@ -395,6 +401,7 @@ var (
Rank: "ping/pong-b",
Pseudo: false,
Shape: pentagon,
+ NodeCount: 1,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ServerProcessNodeID],
fixture.Report.Container.Nodes[fixture.ServerContainerNodeID],
@@ -445,6 +452,7 @@ var (
Pseudo: false,
Shape: pentagon,
Stack: true,
+ NodeCount: 2,
Children: report.MakeNodeSet(
fixture.Report.Process.Nodes[fixture.ClientProcess1NodeID],
fixture.Report.Process.Nodes[fixture.ClientProcess2NodeID],
diff --git a/render/mapping.go b/render/mapping.go
index be6526634..0391b834d 100644
--- a/render/mapping.go
+++ b/render/mapping.go
@@ -514,6 +514,7 @@ func MapCountProcessName(n RenderableNode, _ report.Networks) RenderableNodes {
}
processes, _ := n.Node.Counters.Lookup(processesKey)
+ n.NodeCount = processes
if processes == 1 {
n.LabelMinor = "1 process"
} else {
@@ -744,6 +745,7 @@ func MapCountContainers(n RenderableNode, _ report.Networks) RenderableNodes {
}
containers, _ := n.Node.Counters.Lookup(ContainersKey)
+ n.NodeCount = containers
if containers == 1 {
n.LabelMinor = "1 container"
} else {
@@ -760,6 +762,7 @@ func MapCountPods(n RenderableNode, _ report.Networks) RenderableNodes {
}
pods, _ := n.Node.Counters.Lookup(podsKey)
+ n.NodeCount = pods
if pods == 1 {
n.LabelMinor = "1 pod"
} else {
diff --git a/render/renderable_node.go b/render/renderable_node.go
index c35357cd8..56413b952 100644
--- a/render/renderable_node.go
+++ b/render/renderable_node.go
@@ -17,6 +17,7 @@ type RenderableNode struct {
ControlNode string `json:"-"` // ID of node from which to show the controls in the UI
Shape string `json:"shape"` // Shape node should be rendered as
Stack bool `json:"stack"` // Should UI render this node as a stack?
+ NodeCount int `json:"node_count,omitempty"` // Number of nodes represented by this stack.
report.EdgeMetadata `json:"metadata"` // Numeric sums
report.Node
@@ -42,6 +43,7 @@ func NewRenderableNode(id string) RenderableNode {
EdgeMetadata: report.EdgeMetadata{},
Node: report.MakeNode(),
Shape: Circle,
+ NodeCount: 0,
}
}
@@ -57,6 +59,7 @@ func NewRenderableNodeWith(id, major, minor, rank string, node RenderableNode) R
EdgeMetadata: node.EdgeMetadata.Copy(),
Node: node.Node.Copy(),
Shape: Circle,
+ NodeCount: 0,
}
}
@@ -73,6 +76,7 @@ func NewDerivedNode(id string, node RenderableNode) RenderableNode {
Node: node.Node.Copy(),
ControlNode: "", // Do not propagate ControlNode when making a derived node!
Shape: Circle,
+ NodeCount: 0,
}
}
@@ -87,6 +91,7 @@ func newDerivedPseudoNode(id, major string, node RenderableNode) RenderableNode
EdgeMetadata: node.EdgeMetadata.Copy(),
Node: node.Node.Copy(),
Shape: Circle,
+ NodeCount: 0,
}
}
@@ -128,6 +133,10 @@ func (rn RenderableNode) Merge(other RenderableNode) RenderableNode {
panic(result.ID)
}
+ if result.NodeCount == 0 {
+ result.NodeCount = other.NodeCount
+ }
+
result.Stack = result.Stack || rn.Stack
result.Children = rn.Children.Merge(other.Children)
result.EdgeMetadata = rn.EdgeMetadata.Merge(other.EdgeMetadata)
@@ -150,6 +159,7 @@ func (rn RenderableNode) Copy() RenderableNode {
ControlNode: rn.ControlNode,
Shape: rn.Shape,
Stack: rn.Stack,
+ NodeCount: rn.NodeCount,
}
}
diff --git a/tools/lint b/tools/lint
index 89d534ba8..a2c405797 100755
--- a/tools/lint
+++ b/tools/lint
@@ -148,7 +148,7 @@ function lint_files {
function list_files {
if [ $# -gt 0 ]; then
- find "$@" -type f | grep -vE '(^\./\.git|^\./\.pkg|/vendor/)'
+ find "$@" -type f | grep -vE '(^\./\.git|^\./\.pkg|/vendor/|/client/node_modules/)'
else
git diff --cached --name-only
fi