Skip to content

Commit

Permalink
Merge pull request #797 from weaveworks/758-independent-node-controls
Browse files Browse the repository at this point in the history
Fix node controls so they behave independently across nodes
  • Loading branch information
foot committed Jan 19, 2016
2 parents 4c4748e + 5b39099 commit 359ec29
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 43 deletions.
28 changes: 14 additions & 14 deletions client/app/scripts/actions/app-actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import debug from 'debug';
import AppDispatcher from '../dispatcher/app-dispatcher';
import ActionTypes from '../constants/action-types';
import { updateRoute } from '../utils/router-utils';
import { doControl as doControlRequest, getNodesDelta, getNodeDetails,
import { doControlRequest, getNodesDelta, getNodeDetails,
getTopologies, deletePipe } from '../utils/web-api-utils';
import AppStore from '../stores/app-store';

Expand Down Expand Up @@ -79,9 +79,10 @@ export function openWebsocket() {
});
}

export function clearControlError() {
export function clearControlError(nodeId) {
AppDispatcher.dispatch({
type: ActionTypes.CLEAR_CONTROL_ERROR
type: ActionTypes.CLEAR_CONTROL_ERROR,
nodeId: nodeId
});
}

Expand All @@ -91,15 +92,12 @@ export function closeWebsocket() {
});
}

export function doControl(probeId, nodeId, control) {
export function doControl(nodeId, control) {
AppDispatcher.dispatch({
type: ActionTypes.DO_CONTROL
type: ActionTypes.DO_CONTROL,
nodeId: nodeId
});
doControlRequest(
probeId,
nodeId,
control
);
doControlRequest(nodeId, control);
}

export function enterEdge(edgeId) {
Expand Down Expand Up @@ -144,16 +142,18 @@ export function leaveNode(nodeId) {
});
}

export function receiveControlError(err) {
export function receiveControlError(nodeId, err) {
AppDispatcher.dispatch({
type: ActionTypes.DO_CONTROL_ERROR,
nodeId: nodeId,
error: err
});
}

export function receiveControlSuccess() {
export function receiveControlSuccess(nodeId) {
AppDispatcher.dispatch({
type: ActionTypes.DO_CONTROL_SUCCESS
type: ActionTypes.DO_CONTROL_SUCCESS,
nodeId: nodeId
});
}

Expand Down Expand Up @@ -203,7 +203,7 @@ export function receiveControlPipeFromParams(pipeId, rawTty) {
}

export function receiveControlPipe(pipeId, nodeId, rawTty) {
if (nodeId.split(';').pop() !== AppStore.getSelectedNodeId()) {
if (nodeId !== AppStore.getSelectedNodeId()) {
log('Node was deselected before we could set up control!');
deletePipe(pipeId);
return;
Expand Down
6 changes: 2 additions & 4 deletions client/app/scripts/components/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ const ESC_KEY_CODE = 27;
function getStateFromStores() {
return {
activeTopologyOptions: AppStore.getActiveTopologyOptions(),
controlError: AppStore.getControlError(),
controlPending: AppStore.isControlPending(),
controlStatus: AppStore.getControlStatus(),
controlPipe: AppStore.getControlPipe(),
currentTopology: AppStore.getCurrentTopology(),
currentTopologyId: AppStore.getCurrentTopologyId(),
Expand Down Expand Up @@ -82,9 +81,8 @@ export default class App extends React.Component {
<div className="app">
{showingDebugToolbar() && <DebugToolbar />}
{showingDetails && <Details nodes={this.state.nodes}
controlError={this.state.controlError}
controlPending={this.state.controlPending}
nodeId={this.state.selectedNodeId}
controlStatus={this.state.controlStatus[this.state.selectedNodeId]}
details={this.state.nodeDetails} />}

{showingTerminal && <EmbeddedTerminal
Expand Down
7 changes: 5 additions & 2 deletions client/app/scripts/components/node-details.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export default class NodeDetails extends React.Component {
renderDetails() {
const details = this.props.details;
const nodeColor = getNodeColorDark(details.rank, details.label_major);
const {error, pending} = (this.props.controlStatus || {});
const styles = {
controls: {
'backgroundColor': brightenColor(nodeColor)
Expand All @@ -109,8 +110,10 @@ export default class NodeDetails extends React.Component {
</div>

{details.controls && details.controls.length > 0 && <div className="node-details-controls-wrapper" style={styles.controls}>
<NodeDetailsControls controls={details.controls}
pending={this.props.controlPending} error={this.props.controlError} />
<NodeDetailsControls nodeId={this.props.nodeId}
controls={details.controls}
pending={pending}
error={error} />
</div>}

<div className="node-details-content">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ export default class NodeDetailsControlButton extends React.Component {

handleClick(ev) {
ev.preventDefault();
doControl(this.props.control.probeId, this.props.control.nodeId, this.props.control.id);
doControl(this.props.nodeId, this.props.control);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class NodeDetailsControls extends React.Component {
<span className="node-details-controls-buttons">
{this.props.controls && this.props.controls.map(control => {
return (
<NodeDetailsControlButton control={control}
<NodeDetailsControlButton nodeId={this.props.nodeId} control={control}
pending={this.props.pending} key={control.id} />
);
})}
Expand Down
32 changes: 17 additions & 15 deletions client/app/scripts/stores/app-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import AppDispatcher from '../dispatcher/app-dispatcher';
import ActionTypes from '../constants/action-types';
import { EDGE_ID_SEPARATOR } from '../constants/naming';

const makeMap = Immutable.Map;
const makeOrderedMap = Immutable.OrderedMap;
const makeSet = Immutable.Set;
const log = debug('scope:app-store');
Expand Down Expand Up @@ -48,8 +49,7 @@ function makeNode(node) {

let topologyOptions = makeOrderedMap(); // topologyId -> options
let adjacentNodes = makeSet();
let controlError = null;
let controlPending = false;
let controlStatus = makeMap();
let currentTopology = null;
let currentTopologyId = 'containers';
let errorUrl = null;
Expand Down Expand Up @@ -143,8 +143,8 @@ export class AppStore extends Store {
return adjacentNodes;
}

getControlError() {
return controlError;
getControlStatus() {
return controlStatus.toJS();
}

getControlPipe() {
Expand Down Expand Up @@ -230,10 +230,6 @@ export class AppStore extends Store {
return version;
}

isControlPending() {
return controlPending;
}

isRouteSet() {
return routeSet;
}
Expand Down Expand Up @@ -269,7 +265,7 @@ export class AppStore extends Store {
break;

case ActionTypes.CLEAR_CONTROL_ERROR:
controlError = null;
controlStatus = controlStatus.removeIn([payload.nodeId, 'error']);
this.__emitChange();
break;

Expand Down Expand Up @@ -307,8 +303,10 @@ export class AppStore extends Store {
break;

case ActionTypes.DO_CONTROL:
controlPending = true;
controlError = null;
controlStatus = controlStatus.set(payload.nodeId, makeMap({
pending: true,
error: null
}));
this.__emitChange();
break;

Expand Down Expand Up @@ -346,14 +344,18 @@ export class AppStore extends Store {
break;

case ActionTypes.DO_CONTROL_ERROR:
controlPending = false;
controlError = payload.error;
controlStatus = controlStatus.set(payload.nodeId, makeMap({
pending: false,
error: payload.error
}));
this.__emitChange();
break;

case ActionTypes.DO_CONTROL_SUCCESS:
controlPending = false;
controlError = null;
controlStatus = controlStatus.set(payload.nodeId, makeMap({
pending: false,
error: null
}));
this.__emitChange();
break;

Expand Down
12 changes: 6 additions & 6 deletions client/app/scripts/utils/web-api-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,23 +155,23 @@ export function getApiDetails() {
});
}

export function doControl(probeId, nodeId, control) {
export function doControlRequest(nodeId, control) {
clearTimeout(controlErrorTimer);
const url = `api/control/${encodeURIComponent(probeId)}/`
+ `${encodeURIComponent(nodeId)}/${control}`;
const url = `api/control/${encodeURIComponent(control.probeId)}/`
+ `${encodeURIComponent(control.nodeId)}/${control.id}`;
reqwest({
method: 'POST',
url: url,
success: function(res) {
receiveControlSuccess();
receiveControlSuccess(nodeId);
if (res && res.pipe) {
receiveControlPipe(res.pipe, nodeId, res.raw_tty, true);
}
},
error: function(err) {
receiveControlError(err.response);
receiveControlError(nodeId, err.response);
controlErrorTimer = setTimeout(function() {
clearControlError();
clearControlError(nodeId);
}, 10000);
}
});
Expand Down

0 comments on commit 359ec29

Please sign in to comment.