-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Polish Sentinel dashboard frontend for cluster flow control enhancement
- Add cluster server list and assign page and client list page (for a specific app) Signed-off-by: Eric Zhao <[email protected]>
- Loading branch information
Showing
34 changed files
with
2,299 additions
and
163 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
283 changes: 283 additions & 0 deletions
283
...-dashboard/src/main/webapp/resources/app/scripts/controllers/cluster_app_assign_manage.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,283 @@ | ||
var app = angular.module('sentinelDashboardApp'); | ||
|
||
app.controller('SentinelClusterAppAssignManageController', ['$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; | ||
const DEFAULT_CLUSTER_SERVER_PORT = 18730; | ||
|
||
$scope.tmp = { | ||
curClientChosen: [], | ||
curRemainingClientChosen: [], | ||
curChosenServer: {}, | ||
}; | ||
|
||
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 processAppSingleData(data) { | ||
if (data.state.server && data.state.server.namespaceSet) { | ||
data.state.server.namespaceSetStr = convertSetToString(data.state.server.namespaceSet); | ||
data.mode = data.state.stateInfo.mode; | ||
} | ||
} | ||
|
||
function removeFromArr(arr, v) { | ||
for (let i = 0; i < arr.length; i++) { | ||
if (arr[i] === v) { | ||
arr.splice(i, 1); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
function resetChosen() { | ||
$scope.tmp.curClientChosen = []; | ||
$scope.tmp.curRemainingClientChosen = []; | ||
} | ||
|
||
function generateMachineId(e) { | ||
return e.ip + '@' + e.commandPort; | ||
} | ||
|
||
function applyClusterMap(appClusterMachineList) { | ||
if (!appClusterMachineList) { | ||
return; | ||
} | ||
let tmpMap = new Map(); | ||
$scope.clusterMap = []; | ||
$scope.remainingClientAddressList = []; | ||
let tmpServerList = []; | ||
let tmpClientList = []; | ||
appClusterMachineList.forEach((e) => { | ||
if (e.mode === CLUSTER_MODE_CLIENT) { | ||
tmpClientList.push(e); | ||
} else if (e.mode === CLUSTER_MODE_SERVER) { | ||
tmpServerList.push(e); | ||
} else { | ||
$scope.remainingClientAddressList.push(generateMachineId(e)); | ||
} | ||
}); | ||
tmpServerList.forEach((e) => { | ||
let ip = e.ip; | ||
let machineId = ip + '@' + e.commandPort; | ||
let group = { | ||
ip: ip, | ||
machineId: machineId, | ||
port: e.state.server.port, | ||
clientSet: [], | ||
namespaceSetStr: e.state.server.namespaceSetStr, | ||
belongToApp: true, | ||
}; | ||
if (!tmpMap.has(ip)) { | ||
tmpMap.set(ip, group); | ||
} | ||
}); | ||
tmpClientList.forEach((e) => { | ||
let ip = e.ip; | ||
let machineId = ip + '@' + e.commandPort; | ||
|
||
let targetServer = e.state.client.clientConfig.serverHost; | ||
let targetPort = e.state.client.clientConfig.serverPort; | ||
if (targetServer === undefined || targetServer === '' || | ||
targetPort === undefined || targetPort <= 0) { | ||
$scope.remainingClientAddressList.push(generateMachineId(e)); | ||
return; | ||
} | ||
|
||
if (!tmpMap.has(targetServer)) { | ||
let group = { | ||
ip: targetServer, | ||
machineId: targetServer, | ||
port: targetPort, | ||
clientSet: [machineId], | ||
belongToApp: false, | ||
}; | ||
tmpMap.set(targetServer, group); | ||
} else { | ||
let g = tmpMap.get(targetServer); | ||
g.clientSet.push(machineId); | ||
} | ||
}); | ||
tmpMap.forEach((v) => { | ||
if (v !== undefined) { | ||
$scope.clusterMap.push(v); | ||
} | ||
}); | ||
} | ||
|
||
$scope.onCurrentServerChange = () => { | ||
resetChosen(); | ||
}; | ||
|
||
$scope.remainingClientAddressList = []; | ||
|
||
$scope.moveToServerGroup = () => { | ||
let chosenServer = $scope.tmp.curChosenServer; | ||
if (!chosenServer || !chosenServer.machineId) { | ||
return; | ||
} | ||
$scope.tmp.curRemainingClientChosen.forEach(e => { | ||
chosenServer.clientSet.push(e); | ||
removeFromArr($scope.remainingClientAddressList, e); | ||
}); | ||
resetChosen(); | ||
}; | ||
|
||
$scope.moveToRemainingSharePool = () => { | ||
$scope.tmp.curClientChosen.forEach(e => { | ||
$scope.remainingClientAddressList.push(e); | ||
removeFromArr($scope.tmp.curChosenServer.clientSet, e); | ||
}); | ||
resetChosen(); | ||
}; | ||
|
||
function parseIpFromMachineId(machineId) { | ||
if (machineId.indexOf('@') === -1) { | ||
return machineId; | ||
} | ||
let arr = machineId.split('@'); | ||
return arr[0]; | ||
} | ||
|
||
$scope.addToServerList = () => { | ||
let group; | ||
$scope.tmp.curRemainingClientChosen.forEach(e => { | ||
group = { | ||
machineId: e, | ||
ip: parseIpFromMachineId(e), | ||
port: DEFAULT_CLUSTER_SERVER_PORT, | ||
clientSet: [], | ||
namespaceSetStr: 'default,' + $scope.app, | ||
belongToApp: true, | ||
}; | ||
$scope.clusterMap.push(group); | ||
removeFromArr($scope.remainingClientAddressList, e); | ||
$scope.tmp.curChosenServer = group; | ||
}); | ||
resetChosen(); | ||
}; | ||
|
||
$scope.removeFromServerList = () => { | ||
let chosenServer = $scope.tmp.curChosenServer; | ||
if (!chosenServer || !chosenServer.machineId) { | ||
return; | ||
} | ||
chosenServer.clientSet.forEach((e) => { | ||
if (e !== undefined) { | ||
$scope.remainingClientAddressList.push(e); | ||
} | ||
}); | ||
|
||
if (chosenServer.belongToApp || chosenServer.machineId.indexOf('@') !== -1) { | ||
$scope.remainingClientAddressList.push(chosenServer.machineId); | ||
} else { | ||
alert('提示:非本应用内机器将不会置回空闲列表中'); | ||
} | ||
|
||
removeFromArr($scope.clusterMap, chosenServer); | ||
|
||
resetChosen(); | ||
|
||
if ($scope.clusterMap.length > 0) { | ||
$scope.tmp.curChosenServer = $scope.clusterMap[0]; | ||
$scope.onCurrentServerChange(); | ||
} else { | ||
$scope.tmp.curChosenServer = {}; | ||
} | ||
}; | ||
|
||
function retrieveClusterAppInfo() { | ||
ClusterStateService.fetchClusterUniversalStateOfApp($scope.app).success(function (data) { | ||
if (data.code === 0 && data.data) { | ||
$scope.loadError = undefined; | ||
$scope.appClusterMachineList = data.data; | ||
$scope.appClusterMachineList.forEach(processAppSingleData); | ||
applyClusterMap($scope.appClusterMachineList); | ||
if ($scope.clusterMap.length > 0) { | ||
$scope.tmp.curChosenServer = $scope.clusterMap[0]; | ||
$scope.onCurrentServerChange(); | ||
} | ||
} else { | ||
$scope.appClusterMachineList = {}; | ||
if (data.code === UNSUPPORTED_CODE) { | ||
$scope.loadError = {message: '该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'} | ||
} else { | ||
$scope.loadError = {message: data.msg}; | ||
} | ||
} | ||
}).error(() => { | ||
$scope.loadError = {message: '未知错误'}; | ||
}); | ||
} | ||
|
||
retrieveClusterAppInfo(); | ||
|
||
$scope.saveAndApplyAssign = () => { | ||
let ok = confirm('是否确认执行变更?'); | ||
if (!ok) { | ||
return; | ||
} | ||
let cm = $scope.clusterMap; | ||
if (!cm) { | ||
cm = []; | ||
} | ||
cm.forEach((e) => { | ||
e.namespaceSet = convertStrToNamespaceSet(e.namespaceSetStr); | ||
}); | ||
cm.namespaceSet = convertStrToNamespaceSet(cm.namespaceSetStr); | ||
let request = { | ||
clusterMap: cm, | ||
remainingList: $scope.remainingClientAddressList, | ||
}; | ||
ClusterStateService.applyClusterFullAssignOfApp($scope.app, request).success((data) => { | ||
if (data.code === 0 && data.data) { | ||
let failedServerSet = data.data.failedServerSet; | ||
let failedClientSet = data.data.failedClientSet; | ||
if (failedClientSet.length === 0 && failedServerSet.length === 0) { | ||
alert('全部推送成功'); | ||
} else { | ||
alert('推送完毕。token server 失败列表:' + JSON.stringify(failedServerSet) + | ||
'; token client 失败列表:' + JSON.stringify(failedClientSet)); | ||
} | ||
|
||
retrieveClusterAppInfo(); | ||
} else { | ||
if (data.code === UNSUPPORTED_CODE) { | ||
alert('该应用的 Sentinel 客户端不支持集群限流,请升级至 1.4.0 以上版本并引入相关依赖。'); | ||
} else { | ||
alert('推送失败:' + data.msg); | ||
} | ||
} | ||
}).error(() => { | ||
alert('未知错误'); | ||
}); | ||
}; | ||
}]); |
Oops, something went wrong.