Commit c52a06e0 by Johannes Stelzer

Add support for Spring Cloud Contexts /env endpoint.

This allows to (re-)set properties via POST-requests to the environment endpoint.
parent a374bb23
...@@ -11,7 +11,6 @@ body { ...@@ -11,7 +11,6 @@ body {
margin-bottom: 50px; margin-bottom: 50px;
} }
.center-block { .center-block {
display: block; display: block;
margin-left: auto; margin-left: auto;
...@@ -171,6 +170,12 @@ span.refresh { ...@@ -171,6 +170,12 @@ span.refresh {
color: #f1f1f1; color: #f1f1f1;
} }
.accordion-group,
.boxed {
border: 1px solid #34302D;
}
.sortable { .sortable {
cursor: pointer; cursor: pointer;
} }
......
...@@ -17,12 +17,93 @@ ...@@ -17,12 +17,93 @@
module.exports = function ($scope, application) { module.exports = function ($scope, application) {
$scope.application = application; $scope.application = application;
$scope.override = { values: [{key: '', value: '' }], error: null};
application.getEnv(application) var toArray = function(map) {
var array = [];
for (var key in map) {
var value = map[key];
if (value instanceof Object) {
value = toArray(value);
}
var entry = {key: key, value: value};
array.push(entry);
}
return array.length > 0 ? array : undefined;
};
var collectKeys = function(envArray) {
var allKeys = {};
for (var i = 0; i < envArray.length; i++) {
for (var j = 0; envArray[i].value && j < envArray[i].value.length; j++) {
allKeys[envArray[i].value[j].key] = true;
}
}
return Object.getOwnPropertyNames(allKeys);
};
$scope.reload = function() {
$scope.env = {};
$scope.envArray = [];
$scope.allKeys = [];
application.getEnv()
.success(function (env) { .success(function (env) {
$scope.env = env; $scope.env = env;
$scope.envArray = toArray(env);
$scope.allKeys = collectKeys($scope.envArray);
}) })
.error(function (error) { .error(function (error) {
$scope.error = error; $scope.error = error;
}); });
};
$scope.reload();
var getValue = function(item) {
if (item.key && $scope.allKeys.indexOf(item.key) >= 0) {
application.getEnv(item.key).success(function(value) {
item.value = value;
});
}
};
$scope.onChangeOverrideItem = function(item) {
getValue(item);
if ($scope.override.values[$scope.override.values.length - 1].key) {
$scope.override.values.push({key: '', value: '' });
}
};
$scope.overrideValue = function() {
var map = {};
for (var i = 0; i < $scope.override.values.length; i++) {
if ($scope.override.values[i].key) {
map[$scope.override.values[i].key] = $scope.override.values[i].value;
}
}
$scope.override.error = null;
application.setEnv(map).success(function () {
$scope.override = { values: [{key: '', value: '' }], error: null};
$scope.reload();
})
.error(function (error) {
$scope.override.error = error;
$scope.reload();
});
};
$scope.reset = function() {
$scope.override.error = null;
application.resetEnv().success(function () {
$scope.reload();
})
.error(function (error) {
$scope.override.error = error;
$scope.reload();
});
};
}; };
...@@ -4,9 +4,7 @@ var angular = require('angular'); ...@@ -4,9 +4,7 @@ var angular = require('angular');
var springBootAdmin = angular.module('springBootAdmin'); var springBootAdmin = angular.module('springBootAdmin');
springBootAdmin.filter('timeInterval', require('./timeInterval')); springBootAdmin.filter('timeInterval', require('./timeInterval'));
springBootAdmin.filter('classNameLoggerOnly', require('./classNameLoggerOnly')); springBootAdmin.filter('classNameLoggerOnly', require('./classNameLoggerOnly'));
springBootAdmin.filter('capitalize', require('./capitalize')); springBootAdmin.filter('capitalize', require('./capitalize'));
springBootAdmin.filter('humanBytes', require('./humanBytes')); springBootAdmin.filter('humanBytes', require('./humanBytes'));
springBootAdmin.filter('joinArray', require('./joinArray')); springBootAdmin.filter('joinArray', require('./joinArray'));
springBootAdmin.filter('isEmpty', require('./isEmpty'));
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
module.exports = function () {
return function (obj) {
for (var bar in obj) {
if (obj.hasOwnProperty(bar)) {
return false;
}
}
return true;
};
};
...@@ -18,18 +18,23 @@ var angular = require('angular'); ...@@ -18,18 +18,23 @@ var angular = require('angular');
module.exports = function ($resource, $http) { module.exports = function ($resource, $http) {
var isEndpointEnabled = function(endpoint, configprops) { var isEndpointPresent = function(endpoint, configprops) {
if (configprops[endpoint]) { if (configprops[endpoint]) {
return configprops[endpoint].properties.enabled; return true;
} } else {
return false; return false;
}
}; };
var getCapabilities = function(application) { var getCapabilities = function(application) {
application.capabilities = {}; application.capabilities = {};
$http.get('api/applications/' + application.id + '/configprops').success(function(configprops) { $http.get('api/applications/' + application.id + '/configprops').success(function(configprops) {
application.capabilities.logfile = isEndpointEnabled('logfileEndpoint', configprops); application.capabilities.logfile = isEndpointPresent('logfileEndpoint', configprops);
application.capabilities.activiti = isEndpointEnabled('processEngineEndpoint', configprops); application.capabilities.activiti = isEndpointPresent('processEngineEndpoint', configprops);
application.capabilities.restart = isEndpointPresent('restartEndpoint', configprops);
application.capabilities.refresh = isEndpointPresent('refreshEndpoint', configprops);
application.capabilities.pause = isEndpointPresent('pauseEndpoint', configprops);
application.capabilities.resume = isEndpointPresent('resumeEndpoint', configprops);
}); });
}; };
...@@ -67,8 +72,16 @@ module.exports = function ($resource, $http) { ...@@ -67,8 +72,16 @@ module.exports = function ($resource, $http) {
return $http.get('api/applications/' + this.id + '/metrics'); return $http.get('api/applications/' + this.id + '/metrics');
}; };
Application.prototype.getEnv = function () { Application.prototype.getEnv = function (key) {
return $http.get('api/applications/' + this.id + '/env'); return $http.get('api/applications/' + this.id + '/env' + (key ? '/' + key : '' ));
};
Application.prototype.setEnv = function (map) {
return $http.post('api/applications/' + this.id + '/env', '', {params: map});
};
Application.prototype.resetEnv = function () {
return $http.post('api/applications/' + this.id + '/env/reset');
}; };
Application.prototype.getThreadDump = function () { Application.prototype.getThreadDump = function () {
......
...@@ -3,20 +3,74 @@ ...@@ -3,20 +3,74 @@
<b>Error:</b> {{ error }} <b>Error:</b> {{ error }}
</div> </div>
<div class="row"> <div class="row">
<accordion close-others="false"> <table class="table table-hover boxed">
<accordion-group is-open="true" ng-repeat="(envkey, envvalue) in env track by envkey" heading="{{envkey}}" ng-hide="envvalue | isEmpty"> <thead><tr><th>Profiles <small class="pull-right"><small class="pull-right"><a href="{{ application.managementUrl }}/env">raw JSON</a></small></th></tr></thead>
<small class="pull-right"><a href="{{ application.managementUrl }}/env">raw JSON</a></small> <tbody>
<table class="table table-striped"> <tr ng-repeat="profile in env.profiles" >
<col > <td style="word-break: break-all;" >{{ profile }}</td>
</tr>
<tr ng-hide="env.profiles" >
<td style="word-break: break-all;" >No profiles active</td>
</tr>
</tbody>
</table>
</div>
<div class="row" ng-show="application.capabilities.refresh">
<table class="table table-hover boxed">
<col width="38%">
<col width="62%"> <col width="62%">
<thead><tr><th colspan="2">Overriden properties</th></tr></thead>
<tbody> <tbody>
<tr ng-repeat-end ng-repeat="(key, value) in envvalue" > <tr ng-repeat="(key, value) in env.manager track by key" >
<td style="word-break: break-all;" >{{ key }}</td> <td style="word-break: break-all;" >{{ key }}</td>
<td style="word-break: break-all;" >{{ value }}</td> <td style="word-break: break-all;" >{{ value }}</td>
</tr> </tr>
<tr ng-repeat="item in override.values">
<td >
<input type="text" class="input-xlarge" list="allkeys" placeholder="key" ng-model="item.key" ng-change="onChangeOverrideItem(item)"></input>
<datalist id="allkeys">
<option ng-repeat="key in allKeys | orderBy:'toString()' track by key">{{key}}</option>
</datalist>
</td>
<td>
<input type="text" class="input-xxlarge" placeholder="value" ng-model="item.value"></input>
</td>
</tr>
<tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<div class="control-group pull-right">
<button class="btn btn-warning" ng-click="overrideValue()">Overrride Values!</button>
<button class="btn" ng-click="reset()">Reset Values!</button>
</div>
<div class="alert alert-error" ng-if="override.error">
<b>Error:</b> {{ override.error }}
</div>
</td>
</tr>
</tfoot>
</table>
</div>
<div class="row">
<div>
<div class="input-append">
<input placeholder="Filter by name/value ..." class="input-xxlarge" type="search" ng-model="searchFilter" />
<button class="btn" title="reload list" ng-click="reload()"><i class="icon-refresh"></i></button>
</div>
</div>
<table class="table table-hover boxed" ng-repeat="item in envArray track by item.key" ng-show="item.key != 'profiles' && (item.value | filter:searchFilter).length > 0">
<col width="38%">
<col width="62%">
<thead><tr><th colspan="2">{{item.key}}</th></tr></thead>
<tbody>
<tr ng-repeat="property in item.value | filter:searchFilter track by property.key" >
<td style="word-break: break-all;" >{{ property.key }}</td>
<td style="word-break: break-all;" >{{ property.value }}</td>
</tr>
</tbody> </tbody>
</table> </table>
</accordion-group>
</accordion>
</div> </div>
</div> </div>
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
<span title="filtered / total" class="add-on">{{ filteredLoggers.length }}/{{ loggers.length }}</span> <span title="filtered / total" class="add-on">{{ filteredLoggers.length }}/{{ loggers.length }}</span>
</div> </div>
</form> </form>
<table class="table"> <table class="table table-hover">
<tbody> <tbody>
<tr ng-repeat="logger in (filteredLoggers = (loggers | classNameLoggerOnly:!showPackageLoggers | filter:filterLogger) ) | limitTo: limit track by logger.name"> <tr ng-repeat="logger in (filteredLoggers = (loggers | classNameLoggerOnly:!showPackageLoggers | filter:filterLogger) ) | limitTo: limit track by logger.name">
<td> <td>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment