Merge pull request #148 from tomwilkie/145-version

Expose app version number at /api
This commit is contained in:
Tom Wilkie
2015-06-03 14:34:42 +01:00
10 changed files with 2024 additions and 1966 deletions

View File

@@ -1,4 +1,4 @@
.PHONY: all deps static clean
.PHONY: all deps static clean client-lint client-sync
# If you can use Docker without being root, you can `make SUDO= <target>`
SUDO=sudo
@@ -11,7 +11,7 @@ SCOPE_IMAGE=$(DOCKERHUB_USER)/scope
SCOPE_EXPORT=scope.tar
SCOPE_UI_BUILD_EXPORT=scope_ui_build.tar
SCOPE_UI_BUILD_IMAGE=$(DOCKERHUB_USER)/scope-ui-build
SCOPE_VERSION=$(shell git rev-parse HEAD)
SCOPE_VERSION=$(shell git rev-parse --short HEAD)
all: $(SCOPE_EXPORT)
@@ -56,6 +56,11 @@ client-lint:
-v $(shell pwd)/client/test:/home/weave/test \
$(SCOPE_UI_BUILD_IMAGE) npm run lint
client-sync:
docker run -ti --net=host -v $(shell pwd)/client/app:/home/weave/app \
-v $(shell pwd)/client/build:/home/weave/build \
$(SCOPE_UI_BUILD_IMAGE) gulp sync
$(SCOPE_UI_BUILD_EXPORT): client/Dockerfile client/gulpfile.js client/package.json
docker build -t $(SCOPE_UI_BUILD_IMAGE) client
docker save $(SCOPE_UI_BUILD_IMAGE):latest > $@

View File

@@ -13,6 +13,7 @@ import (
func Router(c Reporter) *mux.Router {
router := mux.NewRouter()
get := router.Methods("GET").Subrouter()
get.HandleFunc("/api", apiHandler)
get.HandleFunc("/api/topology", makeTopologyList(c))
get.HandleFunc("/api/topology/{topology}", captureTopology(c, handleTopology))
get.HandleFunc("/api/topology/{topology}/ws", captureTopology(c, handleWs))
@@ -35,6 +36,15 @@ func captureTopology(rep Reporter, f func(Reporter, topologyView, http.ResponseW
}
}
// APIDetails are some generic details that can be fetched from /api
type APIDetails struct {
Version string `json:"version"`
}
func apiHandler(w http.ResponseWriter, r *http.Request) {
respondWith(w, http.StatusOK, APIDetails{Version: version})
}
type topologyView struct {
human string
selector topologySelecter

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@
</div>
<!-- @ifdef DEBUG -->
<script>window.WS_URL = 'ws://localhost:4040';</script>
<script>window.WS_URL = 'ws://' + location.hostname + ':4040';</script>
<!-- @endif -->
<script src="app.js"></script>

View File

@@ -97,6 +97,13 @@ module.exports = {
WebapiUtils.getNodeDetails(AppStore.getCurrentTopologyUrl(), AppStore.getSelectedNodeId());
},
receiveApiDetails: function(apiDetails) {
AppDispatcher.dispatch({
type: ActionTypes.RECEIVE_API_DETAILS,
version: apiDetails.version
});
},
route: function(state) {
AppDispatcher.dispatch({
state: state,

View File

@@ -11,7 +11,6 @@ const Details = require('./details');
const Nodes = require('./nodes');
const RouterUtils = require('../utils/router-utils');
const ESC_KEY_CODE = 27;
function getStateFromStores() {
@@ -24,7 +23,8 @@ function getStateFromStores() {
selectedNodeId: AppStore.getSelectedNodeId(),
nodeDetails: AppStore.getNodeDetails(),
nodes: AppStore.getNodes(),
topologies: AppStore.getTopologies()
topologies: AppStore.getTopologies(),
version: AppStore.getVersion()
};
}
@@ -41,6 +41,7 @@ const App = React.createClass({
RouterUtils.getRouter().start({hashbang: true});
WebapiUtils.getTopologies();
WebapiUtils.getApiDetails();
},
onChange: function() {
@@ -55,6 +56,7 @@ const App = React.createClass({
render: function() {
const showingDetails = this.state.selectedNodeId;
const versionString = this.state.version ? 'Version ' + this.state.version : '';
return (
<div>
@@ -71,6 +73,8 @@ const App = React.createClass({
<Nodes nodes={this.state.nodes} highlightedNodeIds={this.state.highlightedNodeIds}
highlightedEdgeIds={this.state.highlightedEdgeIds} />
<div className="footer">{versionString}</div>
</div>
);
}

View File

@@ -14,5 +14,6 @@ module.exports = keymirror({
RECEIVE_NODES: null,
RECEIVE_NODES_DELTA: null,
RECEIVE_TOPOLOGIES: null,
RECEIVE_API_DETAILS: null,
ROUTE_TOPOLOGY: null
});

View File

@@ -17,6 +17,7 @@ function isUrlForTopologyId(url, topologyId) {
let connectionState = 'disconnected';
let currentGrouping = 'none';
let currentTopologyId = 'containers';
let version = '';
let mouseOverEdgeId = null;
let mouseOverNodeId = null;
let nodes = {};
@@ -108,6 +109,10 @@ const AppStore = assign({}, EventEmitter.prototype, {
getTopologyIdForUrl: function(url) {
return url.split('/').pop();
},
getVersion: function() {
return version;
}
});
@@ -211,6 +216,11 @@ AppStore.registeredCallback = function(payload) {
AppStore.emit(AppStore.CHANGE_EVENT);
break;
case ActionTypes.RECEIVE_API_DETAILS:
version = payload.version;
AppStore.emit(AppStore.CHANGE_EVENT);
break;
case ActionTypes.ROUTE_TOPOLOGY:
nodes = {};
currentTopologyId = payload.state.topologyId;

View File

@@ -10,6 +10,7 @@ let reconnectTimer = 0;
let currentUrl = null;
let updateFrequency = '5s';
let topologyTimer = 0;
let apiDetailsTimer = 0;
function createWebsocket(topologyUrl) {
if (socket) {
@@ -55,11 +56,21 @@ function getNodeDetails(topologyUrl, nodeId) {
}
}
function getApiDetails() {
clearTimeout(apiDetailsTimer);
reqwest('/api', function(res) {
AppActions.receiveApiDetails(res);
apiDetailsTimer = setTimeout(getApiDetails, 10000);
});
}
module.exports = {
getNodeDetails: getNodeDetails,
getTopologies: getTopologies,
getApiDetails: getApiDetails,
getNodesDelta: function(topologyUrl) {
if (topologyUrl && topologyUrl !== currentUrl) {
createWebsocket(topologyUrl);

View File

@@ -56,6 +56,15 @@ body {
z-index: 20;
}
.footer {
position: absolute;
bottom: 16px;
right: 48px;
z-index: 20;
color: @text-tertiary-color;
font-size: 85%;
}
.logo {
margin: -8px 0 0 64px;
height: 64px;