Add frontend service and pages for Sentinel cluster flow control in dashboard
Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
8961927a12
commit
0059b1a42d
|
|
@ -66,22 +66,38 @@ angular
|
|||
}
|
||||
})
|
||||
|
||||
.state('dashboard.flow', {
|
||||
templateUrl: 'app/views/flow.html',
|
||||
url: '/flow/:app',
|
||||
controller: 'FlowCtl',
|
||||
.state('dashboard.flowV1', {
|
||||
templateUrl: 'app/views/flow_old.html',
|
||||
url: '/v1/flow/:app',
|
||||
controller: 'FlowControllerV1',
|
||||
resolve: {
|
||||
loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
|
||||
return $ocLazyLoad.load({
|
||||
name: 'sentinelDashboardApp',
|
||||
files: [
|
||||
'app/scripts/controllers/flow.js',
|
||||
'app/scripts/controllers/flow_old.js',
|
||||
]
|
||||
});
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
.state('dashboard.flow', {
|
||||
templateUrl: 'app/views/flow.html',
|
||||
url: '/flow/:app',
|
||||
controller: 'FlowController',
|
||||
resolve: {
|
||||
loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
|
||||
return $ocLazyLoad.load({
|
||||
name: 'sentinelDashboardApp',
|
||||
files: [
|
||||
'app/scripts/controllers/flow.js',
|
||||
]
|
||||
});
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
.state('dashboard.paramFlow', {
|
||||
templateUrl: 'app/views/param_flow.html',
|
||||
url: '/paramFlow/:app',
|
||||
|
|
@ -98,6 +114,22 @@ angular
|
|||
}
|
||||
})
|
||||
|
||||
.state('dashboard.clusterAll', {
|
||||
templateUrl: 'app/views/cluster.html',
|
||||
url: '/cluster/:app',
|
||||
controller: 'SentinelClusterController',
|
||||
resolve: {
|
||||
loadMyFiles: ['$ocLazyLoad', function ($ocLazyLoad) {
|
||||
return $ocLazyLoad.load({
|
||||
name: 'sentinelDashboardApp',
|
||||
files: [
|
||||
'app/scripts/controllers/cluster.js',
|
||||
]
|
||||
});
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
.state('dashboard.authority', {
|
||||
templateUrl: 'app/views/authority.html',
|
||||
url: '/authority/:app',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,237 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('SentinelClusterController', ['$scope', '$stateParams', 'ngDialog',
|
||||
'MachineService', 'ClusterStateService',
|
||||
function ($scope, $stateParams, ngDialog, MachineService, ClusterStateService) {
|
||||
$scope.app = $stateParams.app;
|
||||
const UNSUPPORTED_CODE = 4041;
|
||||
|
||||
const CLUSTER_MODE_CLIENT = 0;
|
||||
const CLUSTER_MODE_SERVER = 1;
|
||||
|
||||
$scope.macsInputConfig = {
|
||||
searchField: ['text', 'value'],
|
||||
persist: true,
|
||||
create: false,
|
||||
maxItems: 1,
|
||||
render: {
|
||||
item: function (data, escape) {
|
||||
return '<div>' + escape(data.text) + '</div>';
|
||||
}
|
||||
},
|
||||
onChange: function (value, oldValue) {
|
||||
$scope.macInputModel = value;
|
||||
}
|
||||
};
|
||||
|
||||
function convertSetToString(set) {
|
||||
if (set === undefined) {
|
||||
return '';
|
||||
}
|
||||
let s = '';
|
||||
for (let i = 0; i < set.length; i++) {
|
||||
s = s + set[i];
|
||||
if (i < set.length - 1) {
|
||||
s = s + ',';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function convertStrToNamespaceSet(str) {
|
||||
if (str === undefined || str == '') {
|
||||
return [];
|
||||
}
|
||||
let arr = [];
|
||||
let spliced = str.split(',');
|
||||
spliced.forEach((v) => {
|
||||
arr.push(v.trim());
|
||||
});
|
||||
return arr;
|
||||
}
|
||||
|
||||
function fetchMachineClusterState() {
|
||||
if (!$scope.macInputModel) {
|
||||
return;
|
||||
}
|
||||
let mac = $scope.macInputModel.split(':');
|
||||
ClusterStateService.fetchClusterUniversalState($scope.app, mac[0], mac[1]).success(function (data) {
|
||||
if (data.code == 0 && data.data) {
|
||||
$scope.loadError = undefined;
|
||||
$scope.stateVO = data.data;
|
||||
$scope.stateVO.currentMode = $scope.stateVO.stateInfo.mode;
|
||||
if ($scope.stateVO.server && $scope.stateVO.server.namespaceSet) {
|
||||
$scope.stateVO.server.namespaceSetStr = convertSetToString($scope.stateVO.server.namespaceSet);
|
||||
}
|
||||
} else {
|
||||
$scope.stateVO = {};
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
$scope.loadError = {message: '机器 ' + mac[0] + ':' + mac[1] + ' 的 Sentinel 客户端版本不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'}
|
||||
} else {
|
||||
$scope.loadError = {message: data.msg};
|
||||
}
|
||||
}
|
||||
}).error((data, header, config, status) => {
|
||||
$scope.loadError = {message: '未知错误'};
|
||||
});
|
||||
}
|
||||
|
||||
fetchMachineClusterState();
|
||||
|
||||
function checkValidClientConfig(stateVO) {
|
||||
if (!stateVO.client || !stateVO.client.clientConfig) {
|
||||
alert('不合法的配置');
|
||||
return false;
|
||||
}
|
||||
let config = stateVO.client.clientConfig;
|
||||
if (!config.serverHost || config.serverHost.trim() == '') {
|
||||
alert('请输入有效的 Token Server IP');
|
||||
return false;
|
||||
}
|
||||
if (config.serverPort === undefined || config.serverPort <= 0 || config.serverPort > 65535) {
|
||||
alert('请输入有效的 Token Server 端口');
|
||||
return false;
|
||||
}
|
||||
if (config.requestTimeout === undefined || config.requestTimeout <= 0) {
|
||||
alert('请输入有效的请求超时时长');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function sendClusterClientRequest(stateVO) {
|
||||
if (!checkValidClientConfig(stateVO)) {
|
||||
return;
|
||||
}
|
||||
if (!$scope.macInputModel) {
|
||||
return;
|
||||
}
|
||||
let mac = $scope.macInputModel.split(':');
|
||||
let request = {
|
||||
app: $scope.app,
|
||||
ip: mac[0],
|
||||
port: mac[1],
|
||||
};
|
||||
request.mode = CLUSTER_MODE_CLIENT;
|
||||
request.clientConfig = stateVO.client.clientConfig;
|
||||
ClusterStateService.modifyClusterConfig(request).success(function (data) {
|
||||
if (data.code == 0 && data.data) {
|
||||
alert('修改集群限流客户端配置成功');
|
||||
window.location.reload();
|
||||
} else {
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
alert('机器 ' + mac[0] + ':' + mac[1] + ' 的 Sentinel 客户端版本不支持集群限流客户端,请升级至 1.4.0 以上版本并引入相关依赖。');
|
||||
} else {
|
||||
alert('修改失败:' + data.msg);
|
||||
}
|
||||
}
|
||||
}).error((data, header, config, status) => {
|
||||
alert('未知错误');
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServerConfig(stateVO) {
|
||||
if (!stateVO.server || !stateVO.server.transport) {
|
||||
alert('不合法的配置');
|
||||
return false;
|
||||
}
|
||||
if (stateVO.server.namespaceSetStr === undefined || stateVO.server.namespaceSetStr == '') {
|
||||
alert('请输入有效的命名空间集合(多个 namespace 以 , 分隔)');
|
||||
return false;
|
||||
}
|
||||
let transportConfig = stateVO.server.transport;
|
||||
if (transportConfig.port === undefined || transportConfig.port <= 0 || transportConfig.port > 65535) {
|
||||
alert('请输入有效的 Token Server 端口');
|
||||
return false;
|
||||
}
|
||||
// if (transportConfig.idleSeconds === undefined || transportConfig.idleSeconds <= 0) {
|
||||
// alert('请输入有效的连接清理时长 (idleSeconds)');
|
||||
// return false;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
function sendClusterServerRequest(stateVO) {
|
||||
if (!checkValidServerConfig(stateVO)) {
|
||||
return;
|
||||
}
|
||||
if (!$scope.macInputModel) {
|
||||
return;
|
||||
}
|
||||
let mac = $scope.macInputModel.split(':');
|
||||
let request = {
|
||||
app: $scope.app,
|
||||
ip: mac[0],
|
||||
port: mac[1],
|
||||
};
|
||||
request.mode = CLUSTER_MODE_SERVER;
|
||||
request.flowConfig = stateVO.server.flow;
|
||||
request.transportConfig = stateVO.server.transport;
|
||||
request.namespaceSet = convertStrToNamespaceSet(stateVO.server.namespaceSetStr);
|
||||
ClusterStateService.modifyClusterConfig(request).success(function (data) {
|
||||
if (data.code == 0 && data.data) {
|
||||
alert('修改集群限流服务端配置成功');
|
||||
window.location.reload();
|
||||
} else {
|
||||
if (data.code === UNSUPPORTED_CODE) {
|
||||
alert('机器 ' + mac[0] + ':' + mac[1] + ' 的 Sentinel 客户端版本不支持集群限流服务端,请升级至 1.4.0 以上版本并引入相关依赖。');
|
||||
} else {
|
||||
alert('修改失败:' + data.msg);
|
||||
}
|
||||
}
|
||||
}).error((data, header, config, status) => {
|
||||
alert('未知错误');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
$scope.saveConfig = () => {
|
||||
let ok = confirm('是否确定修改集群限流配置?');
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
let mode = $scope.stateVO.stateInfo.mode;
|
||||
if (mode != 1 && mode != 0) {
|
||||
alert('未知的集群限流模式');
|
||||
return;
|
||||
}
|
||||
if (mode == 0) {
|
||||
sendClusterClientRequest($scope.stateVO);
|
||||
} else {
|
||||
sendClusterServerRequest($scope.stateVO);
|
||||
}
|
||||
};
|
||||
|
||||
function queryAppMachines() {
|
||||
MachineService.getAppMachines($scope.app).success(
|
||||
function (data) {
|
||||
if (data.code == 0) {
|
||||
// $scope.machines = data.data;
|
||||
if (data.data) {
|
||||
$scope.machines = [];
|
||||
$scope.macsInputOptions = [];
|
||||
data.data.forEach(function (item) {
|
||||
if (item.health) {
|
||||
$scope.macsInputOptions.push({
|
||||
text: item.ip + ':' + item.port,
|
||||
value: item.ip + ':' + item.port
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if ($scope.macsInputOptions.length > 0) {
|
||||
$scope.macInputModel = $scope.macsInputOptions[0].value;
|
||||
}
|
||||
} else {
|
||||
$scope.macsInputOptions = [];
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
$scope.$watch('macInputModel', function () {
|
||||
if ($scope.macInputModel) {
|
||||
fetchMachineClusterState();
|
||||
}
|
||||
});
|
||||
queryAppMachines();
|
||||
}]);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('FlowCtl', ['$scope', '$stateParams', 'FlowService', 'ngDialog',
|
||||
app.controller('FlowController', ['$scope', '$stateParams', 'FlowServiceV2', 'ngDialog',
|
||||
'MachineService',
|
||||
function ($scope, $stateParams, FlowService, ngDialog,
|
||||
MachineService) {
|
||||
|
|
@ -72,7 +72,11 @@ app.controller('FlowCtl', ['$scope', '$stateParams', 'FlowService', 'ngDialog',
|
|||
app: $scope.app,
|
||||
ip: mac[0],
|
||||
port: mac[1],
|
||||
limitApp: 'default'
|
||||
limitApp: 'default',
|
||||
clusterMode: false,
|
||||
clusterConfig: {
|
||||
thresholdType: 0
|
||||
}
|
||||
};
|
||||
$scope.flowRuleDialog = {
|
||||
title: '新增流控规则',
|
||||
|
|
|
|||
203
sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_old.js
Executable file
203
sentinel-dashboard/src/main/webapp/resources/app/scripts/controllers/flow_old.js
Executable file
|
|
@ -0,0 +1,203 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('FlowControllerV1', ['$scope', '$stateParams', 'FlowServiceV1', 'ngDialog',
|
||||
'MachineService',
|
||||
function ($scope, $stateParams, FlowService, ngDialog,
|
||||
MachineService) {
|
||||
$scope.app = $stateParams.app;
|
||||
|
||||
$scope.rulesPageConfig = {
|
||||
pageSize: 10,
|
||||
currentPageIndex: 1,
|
||||
totalPage: 1,
|
||||
totalCount: 0,
|
||||
};
|
||||
$scope.macsInputConfig = {
|
||||
searchField: ['text', 'value'],
|
||||
persist: true,
|
||||
create: false,
|
||||
maxItems: 1,
|
||||
render: {
|
||||
item: function (data, escape) {
|
||||
return '<div>' + escape(data.text) + '</div>';
|
||||
}
|
||||
},
|
||||
onChange: function (value, oldValue) {
|
||||
$scope.macInputModel = value;
|
||||
}
|
||||
};
|
||||
|
||||
getMachineRules();
|
||||
function getMachineRules() {
|
||||
if (!$scope.macInputModel) {
|
||||
return;
|
||||
}
|
||||
var mac = $scope.macInputModel.split(':');
|
||||
FlowService.queryMachineRules($scope.app, mac[0], mac[1]).success(
|
||||
function (data) {
|
||||
if (data.code == 0 && data.data) {
|
||||
$scope.rules = data.data;
|
||||
$scope.rulesPageConfig.totalCount = $scope.rules.length;
|
||||
} else {
|
||||
$scope.rules = [];
|
||||
$scope.rulesPageConfig.totalCount = 0;
|
||||
}
|
||||
});
|
||||
};
|
||||
$scope.getMachineRules = getMachineRules;
|
||||
|
||||
var flowRuleDialog;
|
||||
$scope.editRule = function (rule) {
|
||||
$scope.currentRule = rule;
|
||||
$scope.flowRuleDialog = {
|
||||
title: '编辑流控规则',
|
||||
type: 'edit',
|
||||
confirmBtnText: '保存',
|
||||
showAdvanceButton: rule.controlBehavior == 0 && rule.strategy == 0
|
||||
};
|
||||
flowRuleDialog = ngDialog.open({
|
||||
template: '/app/views/dialog/flow-rule-dialog.html',
|
||||
width: 680,
|
||||
overlay: true,
|
||||
scope: $scope
|
||||
});
|
||||
};
|
||||
|
||||
$scope.addNewRule = function () {
|
||||
var mac = $scope.macInputModel.split(':');
|
||||
$scope.currentRule = {
|
||||
grade: 1,
|
||||
strategy: 0,
|
||||
controlBehavior: 0,
|
||||
app: $scope.app,
|
||||
ip: mac[0],
|
||||
port: mac[1],
|
||||
limitApp: 'default'
|
||||
};
|
||||
$scope.flowRuleDialog = {
|
||||
title: '新增流控规则',
|
||||
type: 'add',
|
||||
confirmBtnText: '新增',
|
||||
showAdvanceButton: true,
|
||||
};
|
||||
flowRuleDialog = ngDialog.open({
|
||||
template: '/app/views/dialog/flow-rule-dialog.html',
|
||||
width: 680,
|
||||
overlay: true,
|
||||
scope: $scope
|
||||
});
|
||||
};
|
||||
|
||||
$scope.saveRule = function () {
|
||||
if (!FlowService.checkRuleValid($scope.currentRule)) {
|
||||
return;
|
||||
}
|
||||
if ($scope.flowRuleDialog.type === 'add') {
|
||||
addNewRule($scope.currentRule);
|
||||
} else if ($scope.flowRuleDialog.type === 'edit') {
|
||||
saveRule($scope.currentRule, true);
|
||||
}
|
||||
};
|
||||
|
||||
var confirmDialog;
|
||||
$scope.deleteRule = function (rule) {
|
||||
$scope.currentRule = rule;
|
||||
$scope.confirmDialog = {
|
||||
title: '删除流控规则',
|
||||
type: 'delete_rule',
|
||||
attentionTitle: '请确认是否删除如下流控规则',
|
||||
attention: '资源名: ' + rule.resource + ', 流控应用: ' + rule.limitApp
|
||||
+ ', 阈值类型: ' + (rule.grade == 0 ? '线程数' : 'QPS') + ', 阈值: ' + rule.count,
|
||||
confirmBtnText: '删除',
|
||||
};
|
||||
confirmDialog = ngDialog.open({
|
||||
template: '/app/views/dialog/confirm-dialog.html',
|
||||
scope: $scope,
|
||||
overlay: true
|
||||
});
|
||||
};
|
||||
|
||||
$scope.confirm = function () {
|
||||
if ($scope.confirmDialog.type === 'delete_rule') {
|
||||
deleteRule($scope.currentRule);
|
||||
} else {
|
||||
console.error('error');
|
||||
}
|
||||
};
|
||||
|
||||
function deleteRule(rule) {
|
||||
FlowService.deleteRule(rule).success(function (data) {
|
||||
if (data.code == 0) {
|
||||
getMachineRules();
|
||||
confirmDialog.close();
|
||||
} else {
|
||||
alert('失败!');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function addNewRule(rule) {
|
||||
FlowService.newRule(rule).success(function (data) {
|
||||
if (data.code == 0) {
|
||||
getMachineRules();
|
||||
flowRuleDialog.close();
|
||||
} else {
|
||||
alert('失败!');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.onOpenAdvanceClick = function () {
|
||||
$scope.flowRuleDialog.showAdvanceButton = false;
|
||||
};
|
||||
$scope.onCloseAdvanceClick = function () {
|
||||
$scope.flowRuleDialog.showAdvanceButton = true;
|
||||
};
|
||||
|
||||
function saveRule(rule, edit) {
|
||||
FlowService.saveRule(rule).success(function (data) {
|
||||
if (data.code == 0) {
|
||||
getMachineRules();
|
||||
if (edit) {
|
||||
flowRuleDialog.close();
|
||||
} else {
|
||||
confirmDialog.close();
|
||||
}
|
||||
} else {
|
||||
alert('失败!');
|
||||
}
|
||||
});
|
||||
}
|
||||
queryAppMachines();
|
||||
function queryAppMachines() {
|
||||
MachineService.getAppMachines($scope.app).success(
|
||||
function (data) {
|
||||
if (data.code == 0) {
|
||||
// $scope.machines = data.data;
|
||||
if (data.data) {
|
||||
$scope.machines = [];
|
||||
$scope.macsInputOptions = [];
|
||||
data.data.forEach(function (item) {
|
||||
if (item.health) {
|
||||
$scope.macsInputOptions.push({
|
||||
text: item.ip + ':' + item.port,
|
||||
value: item.ip + ':' + item.port
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if ($scope.macsInputOptions.length > 0) {
|
||||
$scope.macInputModel = $scope.macsInputOptions[0].value;
|
||||
}
|
||||
} else {
|
||||
$scope.macsInputOptions = [];
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
$scope.$watch('macInputModel', function () {
|
||||
if ($scope.macInputModel) {
|
||||
getMachineRules();
|
||||
}
|
||||
});
|
||||
}]);
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.controller('IdentityCtl', ['$scope', '$stateParams', 'IdentityService',
|
||||
'ngDialog', 'FlowService', 'DegradeService', 'AuthorityRuleService', 'ParamFlowService', 'MachineService',
|
||||
'ngDialog', 'FlowServiceV2', 'DegradeService', 'AuthorityRuleService', 'ParamFlowService', 'MachineService',
|
||||
'$interval', '$location', '$timeout',
|
||||
function ($scope, $stateParams, IdentityService, ngDialog,
|
||||
FlowService, DegradeService, AuthorityRuleService, ParamFlowService, MachineService, $interval, $location, $timeout) {
|
||||
|
|
|
|||
|
|
@ -33,9 +33,13 @@
|
|||
</li>
|
||||
|
||||
<li ui-sref-active="active">
|
||||
<a ui-sref="dashboard.flow({app: entry.app})">
|
||||
<a ui-sref="dashboard.flowV1({app: entry.app})">
|
||||
<i class="glyphicon glyphicon-filter"></i> 流控规则</a>
|
||||
</li>
|
||||
<!--<li ui-sref-active="active">-->
|
||||
<!--<a ui-sref="dashboard.flow({app: entry.app})">-->
|
||||
<!--<i class="glyphicon glyphicon-filter"></i> 流控规则 V1</a>-->
|
||||
<!--</li>-->
|
||||
<li ui-sref-active="active">
|
||||
<a ui-sref="dashboard.degrade({app: entry.app})">
|
||||
<i class="glyphicon glyphicon-flash"></i> 降级规则</a>
|
||||
|
|
@ -52,6 +56,10 @@
|
|||
<a ui-sref="dashboard.authority({app: entry.app})">
|
||||
<i class="glyphicon glyphicon-check"></i> 授权规则</a>
|
||||
</li>
|
||||
<li ui-sref-active="active">
|
||||
<a ui-sref="dashboard.clusterAll({app: entry.app})">
|
||||
<i class="glyphicon glyphicon-cloud"></i> 集群限流</a>
|
||||
</li>
|
||||
<li ui-sref-active="active">
|
||||
<a ui-sref="dashboard.machine({app: entry.app})">
|
||||
<i class="glyphicon glyphicon-th-list"></i> 机器列表</a>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Parameter flow control service.
|
||||
*
|
||||
* @author Eric Zhao
|
||||
*/
|
||||
angular.module('sentinelDashboardApp').service('ClusterStateService', ['$http', function ($http) {
|
||||
|
||||
this.fetchClusterUniversalState = function(app, ip, port) {
|
||||
var param = {
|
||||
app: app,
|
||||
ip: ip,
|
||||
port: port
|
||||
};
|
||||
return $http({
|
||||
url: '/cluster/state',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
this.modifyClusterConfig = function(config) {
|
||||
return $http({
|
||||
url: '/cluster/config/modify',
|
||||
data: config,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
}]);
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.service('FlowService', ['$http', function ($http) {
|
||||
app.service('FlowServiceV1', ['$http', function ($http) {
|
||||
this.queryMachineRules = function (app, ip, port) {
|
||||
var param = {
|
||||
app: app,
|
||||
|
|
@ -8,7 +8,7 @@ app.service('FlowService', ['$http', function ($http) {
|
|||
port: port
|
||||
};
|
||||
return $http({
|
||||
url: 'flow/rules.json',
|
||||
url: '/v1/flow/rules',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
});
|
||||
|
|
@ -31,9 +31,9 @@ app.service('FlowService', ['$http', function ($http) {
|
|||
};
|
||||
|
||||
return $http({
|
||||
url: '/flow/new.json',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
url: '/v1/flow/rule',
|
||||
data: rule,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -52,9 +52,9 @@ app.service('FlowService', ['$http', function ($http) {
|
|||
};
|
||||
|
||||
return $http({
|
||||
url: '/flow/save.json',
|
||||
url: '/v1/flow/save.json',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
method: 'PUT'
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -65,9 +65,9 @@ app.service('FlowService', ['$http', function ($http) {
|
|||
};
|
||||
|
||||
return $http({
|
||||
url: '/flow/delete.json',
|
||||
url: '/v1/flow/delete.json',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
method: 'DELETE'
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
var app = angular.module('sentinelDashboardApp');
|
||||
|
||||
app.service('FlowServiceV2', ['$http', function ($http) {
|
||||
this.queryMachineRules = function (app, ip, port) {
|
||||
var param = {
|
||||
app: app,
|
||||
ip: ip,
|
||||
port: port
|
||||
};
|
||||
return $http({
|
||||
url: '/v2/flow/rules',
|
||||
params: param,
|
||||
method: 'GET'
|
||||
});
|
||||
};
|
||||
|
||||
this.newRule = function (rule) {
|
||||
return $http({
|
||||
url: '/v2/flow/rule',
|
||||
data: rule,
|
||||
method: 'POST'
|
||||
});
|
||||
};
|
||||
|
||||
this.saveRule = function (rule) {
|
||||
return $http({
|
||||
url: '/v2/flow/rule/' + rule.id,
|
||||
data: rule,
|
||||
method: 'PUT'
|
||||
});
|
||||
};
|
||||
|
||||
this.deleteRule = function (rule) {
|
||||
return $http({
|
||||
url: '/v2/flow/rule/' + rule.id,
|
||||
method: 'DELETE'
|
||||
});
|
||||
};
|
||||
|
||||
function notNumberAtLeastZero(num) {
|
||||
return num === undefined || num === '' || isNaN(num) || num < 0;
|
||||
}
|
||||
|
||||
function notNumberGreaterThanZero(num) {
|
||||
return num === undefined || num === '' || isNaN(num) || num <= 0;
|
||||
}
|
||||
|
||||
this.checkRuleValid = function (rule) {
|
||||
if (rule.resource === undefined || rule.resource === '') {
|
||||
alert('资源名称不能为空');
|
||||
return false;
|
||||
}
|
||||
if (rule.count === undefined || rule.count < 0) {
|
||||
alert('限流阈值必须大于等于 0');
|
||||
return false;
|
||||
}
|
||||
if (rule.strategy === undefined || rule.strategy < 0) {
|
||||
alert('无效的流控模式');
|
||||
return false;
|
||||
}
|
||||
if (rule.strategy == 1 || rule.strategy == 2) {
|
||||
if (rule.refResource === undefined || rule.refResource == '') {
|
||||
alert('请填写关联资源或入口');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (rule.controlBehavior === undefined || rule.controlBehavior < 0) {
|
||||
alert('无效的流控整形方式');
|
||||
return false;
|
||||
}
|
||||
if (rule.controlBehavior == 1 && notNumberGreaterThanZero(rule.warmUpPeriodSec)) {
|
||||
alert('预热时长必须大于 0');
|
||||
return false;
|
||||
}
|
||||
if (rule.controlBehavior == 2 && notNumberGreaterThanZero(rule.maxQueueingTimeMs)) {
|
||||
alert('排队超时时间必须大于 0');
|
||||
return false;
|
||||
}
|
||||
if (rule.clusterMode && (rule.clusterConfig === undefined || rule.clusterConfig.thresholdType === undefined)) {
|
||||
alert('集群限流配置不正确');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}]);
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
|
||||
<div class="row" style="margin-left: 1px; margin-top:10px; height: 50px;">
|
||||
<div class="col-md-6" style="margin-bottom: 10px;">
|
||||
<span style="font-size: 30px;font-weight: bold;">{{app}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
<div class="container-fluid">
|
||||
<div class="row" style="margin-top: 20px; margin-bottom: 20px;">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="inputs-header">
|
||||
<span class="brand" style="font-size: 13px;">集群限流</span>
|
||||
<button class="btn btn-primary" style="float: right; margin-right: 10px; height: 30px;font-size: 12px;" ng-click="getMachineRules()">刷新</button>
|
||||
<input class="form-control witdh-200" placeholder="关键字" ng-model="searchKey">
|
||||
<div class="control-group" style="float:right;margin-right: 10px;margin-bottom: -10px;">
|
||||
<selectize id="gsInput" class="selectize-input-200" config="macsInputConfig" options="macsInputOptions" ng-model="macInputModel"
|
||||
placeholder="机器"></selectize>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- error panel -->
|
||||
<div class="row clearfix" ng-if="loadError">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<center>
|
||||
<p>{{loadError.message}}</p>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--.tools-header -->
|
||||
<div class="card-body" style="padding: 0px 0px;">
|
||||
<!--<span class="brand" style="font-weight:bold;">集群限流状态</span>-->
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">当前模式</label>
|
||||
<p class="col-sm-6 control-label" style="text-align: left; font-weight: normal;" ng-if="stateVO.currentMode == 0">Client</p>
|
||||
<p class="col-sm-6 control-label" style="text-align: left; font-weight: normal;" ng-if="stateVO.currentMode == 1">Server</p>
|
||||
<p class="col-sm-6 control-label" style="text-align: left; font-weight: normal;" ng-if="stateVO.currentMode == -1">未开启</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">集群限流模式变换</label>
|
||||
<div class="col-sm-4">
|
||||
<div class="form-control highlight-border" align="center">
|
||||
<input type="radio" name="mode" value="0" ng-model='stateVO.stateInfo.mode' ng-disabled="!stateVO.stateInfo.clientAvailable" /> Client
|
||||
<input type="radio" name="mode" value="1" ng-model='stateVO.stateInfo.mode' ng-disabled="!stateVO.stateInfo.serverAvailable" /> Server
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<!-- no-cluster-mode-available-panel.start -->
|
||||
<div ng-if="!stateVO.stateInfo.clientAvailable && !stateVO.stateInfo.serverAvailable">
|
||||
<!-- error panel -->
|
||||
<div class="row clearfix">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<center>
|
||||
<p>该机器未引入 Sentinel 集群限流客户端或服务端的相关依赖,请引入相关依赖。</p>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- no-cluster-mode-available-panel.stop -->
|
||||
|
||||
<div ng-if="stateVO.stateInfo.clientAvailable || stateVO.stateInfo.serverAvailable">
|
||||
<div ng-if="stateVO.stateInfo.clientAvailable && stateVO.stateInfo.mode == 0">
|
||||
<div ng-include="'app/views/cluster/client.html'"></div>
|
||||
</div>
|
||||
<div ng-if="stateVO.stateInfo.serverAvailable && stateVO.stateInfo.mode == 1">
|
||||
<div ng-include="'app/views/cluster/server.html'"></div>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
<div clss="row" style="margin-top: 20px;">
|
||||
<button style="margin: 0 10px 10px 10px;" class="btn btn-outline-success" ng-click="saveConfig()">保存配置</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- .card-body -->
|
||||
</div>
|
||||
<!-- .card -->
|
||||
</div>
|
||||
<!-- .col-md-12 -->
|
||||
</div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<!-- .container-fluid -->
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<div class="row clearfix">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Token Server IP</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" class="form-control highlight-border" ng-model='stateVO.client.clientConfig.serverHost' placeholder='请指定 Token Server IP' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Token Server 端口</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="0" max="65535" required class="form-control highlight-border" ng-model='stateVO.client.clientConfig.serverPort' placeholder='请指定 Token Server 端口' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">请求超时时间(ms)</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="0" required class="form-control highlight-border" ng-model='stateVO.client.clientConfig.requestTimeout' placeholder='请指定请求超时时间(ms)' />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<div class="row clearfix">
|
||||
<form role="form" class="form-horizontal">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">Token Server 端口</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="number" min="0" max="65535" required class="form-control highlight-border" ng-model='stateVO.server.transport.port' placeholder='请指定 Token Server 端口' />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">命名空间集合</label>
|
||||
<div class="col-sm-4">
|
||||
<input type="text" required class="form-control highlight-border" ng-model='stateVO.server.namespaceSetStr' placeholder='请指定服务端服务的命名空间集合(以,分隔)' />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
@ -30,9 +30,39 @@
|
|||
<input type="radio" name="grade" value="0" ng-model='currentRule.grade' /> 线程数
|
||||
</div>
|
||||
</div>
|
||||
<label class="col-sm-2 control-label">单机阈值</label>
|
||||
<div class="col-sm-3">
|
||||
<input type='number' min="0" class="form-control highlight-border" ng-model='currentRule.count' placeholder="单机阈值" />
|
||||
<div ng-if="!currentRule.clusterMode">
|
||||
<label class="col-sm-2 control-label">单机阈值</label>
|
||||
<div class="col-sm-3">
|
||||
<input type='number' min="0" class="form-control highlight-border" ng-model='currentRule.count' placeholder="单机阈值" />
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="currentRule.clusterMode && currentRule.clusterConfig.thresholdType == 0">
|
||||
<label class="col-sm-2 control-label">均摊阈值</label>
|
||||
<div class="col-sm-3">
|
||||
<input type='number' min="0" class="form-control highlight-border" ng-model='currentRule.count' placeholder="单机均摊阈值" />
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="currentRule.clusterMode && currentRule.clusterConfig.thresholdType == 1">
|
||||
<label class="col-sm-2 control-label">集群阈值</label>
|
||||
<div class="col-sm-3">
|
||||
<input type='number' min="0" class="form-control highlight-border" ng-model='currentRule.count' placeholder="集群总体阈值" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label">是否集群</label>
|
||||
<div class="col-sm-2">
|
||||
<input type="checkbox" name="clusterMode" ng-model="currentRule.clusterMode">
|
||||
</div>
|
||||
<div ng-if="currentRule.clusterMode">
|
||||
<label class="col-sm-3 control-label">集群阈值模式</label>
|
||||
<div class="col-sm-4">
|
||||
<div class="form-control highlight-border" align="center">
|
||||
<input type="radio" name="clusterThresholdType" value="0" ng-model='currentRule.clusterConfig.thresholdType' /> 单机均摊
|
||||
<input type="radio" name="clusterThresholdType" value="1" ng-model='currentRule.clusterConfig.thresholdType' /> Global
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
<span style="font-size: 30px;font-weight: bold;">{{app}}</span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<button class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ng-disabled="!macInputModel" ng-click="addNewRule()">
|
||||
<i class="fa fa-plus"></i> 新增流控规则</button>
|
||||
<button class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ng-click="addNewRule()">
|
||||
<i class="fa fa-plus"></i> 新增流控规则
|
||||
</button>
|
||||
<a class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ui-sref="dashboard.flowV1({app: app})">
|
||||
回到旧版(单机)</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -16,13 +19,7 @@
|
|||
<div class="card">
|
||||
<div class="inputs-header">
|
||||
<span class="brand" style="font-size: 13px;">流控规则</span>
|
||||
<!--<button class="btn btn-danger" style="float: right;margin-right: 10px;height: 30px;font-size: 12px;" ng-click="disableAll()">全部禁用</button>-->
|
||||
<button class="btn btn-primary" style="float: right; margin-right: 10px; height: 30px;font-size: 12px;" ng-click="getMachineRules()">刷新</button>
|
||||
<input class="form-control witdh-200" placeholder="关键字" ng-model="searchKey">
|
||||
<div class="control-group" style="float:right;margin-right: 10px;margin-bottom: -10px;">
|
||||
<selectize id="gsInput" class="selectize-input-200" config="macsInputConfig" options="macsInputOptions" ng-model="macInputModel"
|
||||
placeholder="机器"></selectize>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--.tools-header -->
|
||||
|
|
@ -36,21 +33,21 @@
|
|||
<td style="width: 10%;">
|
||||
流控应用
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
<td style="width: 8%;">
|
||||
流控模式
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
<td style="width: 8%;">
|
||||
阈值类型
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
<td style="width: 8%;">
|
||||
单机阈值
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
<td style="width: 8%;">
|
||||
是否集群
|
||||
</td>
|
||||
<td style="width: 8%;">
|
||||
流控效果
|
||||
</td>
|
||||
<!--<td style="width: 8%;">-->
|
||||
<!--状态-->
|
||||
<!--</td>-->
|
||||
<td style="width: 12%;">
|
||||
操作
|
||||
</td>
|
||||
|
|
@ -67,15 +64,20 @@
|
|||
<span ng-if="rule.strategy == 2">链路</span>
|
||||
</td>
|
||||
<td>
|
||||
{{rule.grade==0 ? '线程数' : 'QPS'}}
|
||||
{{rule.grade == 0 ? '线程数' : 'QPS'}}
|
||||
</td>
|
||||
<td style="word-wrap:break-word;word-break:break-all;">
|
||||
{{rule.count}}
|
||||
</td>
|
||||
<td>
|
||||
<span ng-if="rule.clusterMode">是</span>
|
||||
<span ng-if="!rule.clusterMode">否</span>
|
||||
</td>
|
||||
<td>
|
||||
<span ng-if="rule.controlBehavior == 0">快速失败</span>
|
||||
<span ng-if="rule.controlBehavior == 1">Warm Up</span>
|
||||
<span ng-if="rule.controlBehavior == 2">排队等待</span>
|
||||
<span ng-if="rule.controlBehavior == 3">预热排队</span>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-xs btn-default" type="button" ng-click="editRule(rule)" style="font-size: 12px; height:25px;">编辑</button>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,113 @@
|
|||
<div class="row" style="margin-left: 1px; margin-top:10px; height: 50px;">
|
||||
<div class="col-md-6" style="margin-bottom: 10px;">
|
||||
<span style="font-size: 30px;font-weight: bold;">{{app}}</span>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<button class="btn btn-default-inverse" style="float: right; margin-right: 10px;" ng-disabled="!macInputModel" ng-click="addNewRule()">
|
||||
<i class="fa fa-plus"></i> 新增流控规则</button>
|
||||
<a class="btn btn-outline-success" style="float: right; margin-right: 10px;" ui-sref="dashboard.flow({app: app})">
|
||||
回到新版</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="separator"></div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row" style="margin-top: 20px; margin-bottom: 20px;">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="inputs-header">
|
||||
<span class="brand" style="font-size: 13px;">流控规则</span>
|
||||
<!--<button class="btn btn-danger" style="float: right;margin-right: 10px;height: 30px;font-size: 12px;" ng-click="disableAll()">全部禁用</button>-->
|
||||
<button class="btn btn-primary" style="float: right; margin-right: 10px; height: 30px;font-size: 12px;" ng-click="getMachineRules()">刷新</button>
|
||||
<input class="form-control witdh-200" placeholder="关键字" ng-model="searchKey">
|
||||
<div class="control-group" style="float:right;margin-right: 10px;margin-bottom: -10px;">
|
||||
<selectize id="gsInput" class="selectize-input-200" config="macsInputConfig" options="macsInputOptions" ng-model="macInputModel"
|
||||
placeholder="机器"></selectize>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--.tools-header -->
|
||||
<div class="card-body" style="padding: 0px 0px;">
|
||||
<table class="table" style="border-left: none; border-right:none;margin-top: 10px;">
|
||||
<thead>
|
||||
<tr style="background: #F3F5F7;">
|
||||
<td style="width: 40%">
|
||||
资源名
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
流控应用
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
流控模式
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
阈值类型
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
单机阈值
|
||||
</td>
|
||||
<td style="width: 10%;">
|
||||
流控效果
|
||||
</td>
|
||||
<!--<td style="width: 8%;">-->
|
||||
<!--状态-->
|
||||
<!--</td>-->
|
||||
<td style="width: 12%;">
|
||||
操作
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr dir-paginate="rule in rules | filter: searchKey | itemsPerPage: rulesPageConfig.pageSize " current-page="rulesPageConfig.currentPageIndex"
|
||||
pagination-id="entriesPagination">
|
||||
<td style="word-wrap:break-word;word-break:break-all;">{{rule.resource}}</td>
|
||||
<td style="word-wrap:break-word;word-break:break-all;">{{rule.limitApp }}</td>
|
||||
<td>
|
||||
<span ng-if="rule.strategy == 0">直接</span>
|
||||
<span ng-if="rule.strategy == 1">关联</span>
|
||||
<span ng-if="rule.strategy == 2">链路</span>
|
||||
</td>
|
||||
<td>
|
||||
{{rule.grade==0 ? '线程数' : 'QPS'}}
|
||||
</td>
|
||||
<td style="word-wrap:break-word;word-break:break-all;">
|
||||
{{rule.count}}
|
||||
</td>
|
||||
<td>
|
||||
<span ng-if="rule.controlBehavior == 0">快速失败</span>
|
||||
<span ng-if="rule.controlBehavior == 1">Warm Up</span>
|
||||
<span ng-if="rule.controlBehavior == 2">排队等待</span>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn btn-xs btn-default" type="button" ng-click="editRule(rule)" style="font-size: 12px; height:25px;">编辑</button>
|
||||
<button class="btn btn-xs btn-default" type="button" ng-click="deleteRule(rule)" style="font-size: 12px; height:25px;">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- .card-body -->
|
||||
<div class="pagination-footer">
|
||||
<dir-pagination-controls boundary-links="true" template-url="app/views/pagination.tpl.html" pagination-id="entriesPagination"
|
||||
on-page-change="">
|
||||
</dir-pagination-controls>
|
||||
<div class="tools" style="">
|
||||
<span>共 {{rulesPageConfig.totalCount}} 条记录, </span>
|
||||
<span>
|
||||
每页
|
||||
<input class="form-control" ng-model="rulesPageConfig.pageSize"> 条记录
|
||||
</span>
|
||||
<!--<span>第 {{rulesPageConfig.currentPageIndex}} / {{rulesPageConfig.totalPage}} 页</span>-->
|
||||
</div>
|
||||
<!-- .tools -->
|
||||
</div>
|
||||
<!-- pagination-footer -->
|
||||
</div>
|
||||
<!-- .card -->
|
||||
</div>
|
||||
<!-- .col-md-12 -->
|
||||
</div>
|
||||
<!-- -->
|
||||
</div>
|
||||
<!-- .container-fluid -->
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -44,7 +44,8 @@ const JS_APP = [
|
|||
'app/scripts/app.js',
|
||||
'app/scripts/filters/filters.js',
|
||||
'app/scripts/services/appservice.js',
|
||||
'app/scripts/services/flowservice.js',
|
||||
'app/scripts/services/flow_service_v1.js',
|
||||
'app/scripts/services/flow_service_v2.js',
|
||||
'app/scripts/services/degradeservice.js',
|
||||
'app/scripts/services/systemservice.js',
|
||||
'app/scripts/services/machineservice.js',
|
||||
|
|
@ -52,6 +53,7 @@ const JS_APP = [
|
|||
'app/scripts/services/metricservice.js',
|
||||
'app/scripts/services/param_flow_service.js',
|
||||
'app/scripts/services/authority_service.js',
|
||||
'app/scripts/services/cluster_state_service.js',
|
||||
];
|
||||
|
||||
gulp.task('lib', function () {
|
||||
|
|
|
|||
Loading…
Reference in New Issue