mirror of https://github.com/portainer/portainer
refactor(storidge): move add / remove / put in / put ouf maintenance buttons for cluster nodes
parent
62f6ac926c
commit
46b2124544
|
@ -7,18 +7,23 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="actionBar">
|
<div class="actionBar">
|
||||||
<button type="button" class="btn btn-sm btn-danger"
|
<div class="row">
|
||||||
ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.removeAction($ctrl.state.selectedItems)">
|
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.addNodeAction()">
|
||||||
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove
|
<i class="fa fa-plus space-right" aria-hidden="true"></i>Add node
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-sm btn-primary"
|
<div style="margin-bottom: 0px;">
|
||||||
ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.cordonNodeAction($ctrl.state.selectedItems)">
|
<span ng-if="$ctrl.addInfo" class="text-muted small">
|
||||||
<i class="fas fa-wrench space-right" aria-hidden="true"></i>Put in maintenance
|
To add a node to this cluster, run the following command on your new node
|
||||||
</button>
|
<code>
|
||||||
<button type="button" class="btn btn-sm btn-primary"
|
{{ $ctrl.addInfo }}
|
||||||
ng-disabled="$ctrl.state.selectedItemCount === 0" ng-click="$ctrl.uncordonNodeAction($ctrl.state.selectedItems)">
|
</code>
|
||||||
<i class="fa fa-power-off space-right" aria-hidden="true"></i>Put out of maintenance
|
<span class="btn btn-primary btn-sm space-left" ng-click="$ctrl.copyAddNodeCommand()"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy</span>
|
||||||
</button>
|
<span>
|
||||||
|
<i id="copyNotification" class="fa fa-check green-icon" aria-hidden="true" style="margin-left: 7px; display: none;"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="searchBar">
|
<div class="searchBar">
|
||||||
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
|
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
|
||||||
|
@ -29,10 +34,6 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
<span class="md-checkbox">
|
|
||||||
<input id="select_all" type="checkbox" ng-model="$ctrl.state.selectAll" ng-change="$ctrl.selectAll()" />
|
|
||||||
<label for="select_all"></label>
|
|
||||||
</span>
|
|
||||||
<a ng-click="$ctrl.changeOrderBy('Name')">
|
<a ng-click="$ctrl.changeOrderBy('Name')">
|
||||||
Name
|
Name
|
||||||
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Name' && !$ctrl.state.reverseOrder"></i>
|
<i class="fa fa-sort-alpha-down" aria-hidden="true" ng-if="$ctrl.state.orderBy === 'Name' && !$ctrl.state.reverseOrder"></i>
|
||||||
|
@ -65,10 +66,6 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))" ng-class="{active: item.Checked}">
|
<tr dir-paginate="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit))" ng-class="{active: item.Checked}">
|
||||||
<td>
|
<td>
|
||||||
<span class="md-checkbox">
|
|
||||||
<input id="select_{{ $index }}" type="checkbox" ng-model="item.Checked" ng-change="$ctrl.selectItem(item)"/>
|
|
||||||
<label for="select_{{ $index }}"></label>
|
|
||||||
</span>
|
|
||||||
<a ui-sref="storidge.cluster.node({name: item.Name})"> {{ item.Name }}</a>
|
<a ui-sref="storidge.cluster.node({name: item.Name})"> {{ item.Name }}</a>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ item.IP }}</td>
|
<td>{{ item.IP }}</td>
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
angular.module('extension.storidge').component('storidgeNodesDatatable', {
|
angular.module('extension.storidge').component('storidgeNodesDatatable', {
|
||||||
templateUrl: 'app/extensions/storidge/components/nodes-datatable/storidgeNodesDatatable.html',
|
templateUrl: 'app/extensions/storidge/components/nodes-datatable/storidgeNodesDatatable.html',
|
||||||
controller: 'GenericDatatableController',
|
controller: 'StoridgeNodesDatatableController',
|
||||||
bindings: {
|
bindings: {
|
||||||
titleText: '@',
|
titleText: '@',
|
||||||
titleIcon: '@',
|
titleIcon: '@',
|
||||||
dataset: '<',
|
dataset: '<',
|
||||||
tableKey: '@',
|
tableKey: '@',
|
||||||
orderBy: '@',
|
orderBy: '@',
|
||||||
reverseOrder: '<',
|
reverseOrder: '<'
|
||||||
removeAction: '<',
|
|
||||||
cordonNodeAction: '<',
|
|
||||||
uncordonNodeAction: '<'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
angular.module('extension.storidge')
|
||||||
|
.controller('StoridgeNodesDatatableController', ['$scope', '$controller', 'clipboard', 'Notifications', 'StoridgeNodeService',
|
||||||
|
function($scope, $controller, clipboard, Notifications, StoridgeNodeService) {
|
||||||
|
angular.extend(this, $controller('GenericDatatableController', { $scope: $scope }));
|
||||||
|
|
||||||
|
var ctrl = this;
|
||||||
|
|
||||||
|
this.addNodeAction = function() {
|
||||||
|
StoridgeNodeService.add()
|
||||||
|
.then(function sucess(data) {
|
||||||
|
ctrl.addInfo = data.content;
|
||||||
|
})
|
||||||
|
.catch(function error(err) {
|
||||||
|
Notifications.error('Failure', err, 'Unable to retrieve the "add node" command');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.copyAddNodeCommand = function() {
|
||||||
|
clipboard.copyText(ctrl.addInfo);
|
||||||
|
$('#copyNotification').show();
|
||||||
|
$('#copyNotification').fadeOut(2000);
|
||||||
|
};
|
||||||
|
}]);
|
|
@ -31,23 +31,6 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<form class="form-horizontal">
|
<form class="form-horizontal">
|
||||||
<div class="col-sm-12 form-section-title" >
|
|
||||||
Information
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<span class="col-sm-12 text-muted small">
|
|
||||||
To add a node to this cluster, run the following command on your new node
|
|
||||||
<div style="margin-top: 10px;">
|
|
||||||
<code>
|
|
||||||
{{ addInfo }}
|
|
||||||
</code>
|
|
||||||
<span class="btn btn-primary btn-sm space-left" ng-click="copyAddNodeCommand()"><i class="fa fa-copy space-right" aria-hidden="true"></i>Copy</span>
|
|
||||||
<span>
|
|
||||||
<i id="copyNotification" class="fa fa-check green-icon" aria-hidden="true" style="margin-left: 7px; display: none;"></i>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-12 form-section-title">
|
<div class="col-sm-12 form-section-title">
|
||||||
Actions
|
Actions
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,9 +57,7 @@
|
||||||
<storidge-nodes-datatable
|
<storidge-nodes-datatable
|
||||||
title-text="Storage nodes" title-icon="fa-object-group"
|
title-text="Storage nodes" title-icon="fa-object-group"
|
||||||
dataset="clusterNodes" table-key="storidge_nodes"
|
dataset="clusterNodes" table-key="storidge_nodes"
|
||||||
order-by="Name" remove-action="removeAction"
|
order-by="Name"
|
||||||
cordon-node-action="cordonNodeAction"
|
|
||||||
uncordon-node-action="uncordonNodeAction"
|
|
||||||
></storidge-nodes-datatable>
|
></storidge-nodes-datatable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,126 +1,12 @@
|
||||||
angular.module('extension.storidge')
|
angular.module('extension.storidge')
|
||||||
.controller('StoridgeClusterController', ['$q', '$scope', '$state', 'clipboard', 'Notifications', 'StoridgeClusterService', 'StoridgeNodeService', 'ModalService',
|
.controller('StoridgeClusterController', ['$q', '$scope', '$state', 'Notifications', 'StoridgeClusterService', 'StoridgeNodeService', 'ModalService',
|
||||||
function ($q, $scope, $state, clipboard, Notifications, StoridgeClusterService, StoridgeNodeService, ModalService) {
|
function ($q, $scope, $state, Notifications, StoridgeClusterService, StoridgeNodeService, ModalService) {
|
||||||
|
|
||||||
$scope.state = {
|
$scope.state = {
|
||||||
shutdownInProgress: false,
|
shutdownInProgress: false,
|
||||||
rebootInProgress: false
|
rebootInProgress: false
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.copyAddNodeCommand = function() {
|
|
||||||
clipboard.copyText($scope.addInfo);
|
|
||||||
$('#copyNotification').show();
|
|
||||||
$('#copyNotification').fadeOut(2000);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.removeAction = function(selectedItems) {
|
|
||||||
ModalService.confirm({
|
|
||||||
title: 'Are you sure?',
|
|
||||||
message: 'Do you want really want to remove the nodes from the cluster?',
|
|
||||||
buttons: {
|
|
||||||
confirm: {
|
|
||||||
label: 'Remove',
|
|
||||||
className: 'btn-danger'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
callback: function onConfirm(confirmed) {
|
|
||||||
if(!confirmed) { return; }
|
|
||||||
remove(selectedItems);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function remove(selectedItems) {
|
|
||||||
var actionCount = selectedItems.length;
|
|
||||||
angular.forEach(selectedItems, function (node) {
|
|
||||||
StoridgeNodeService.remove(node.Name)
|
|
||||||
.then(function success() {
|
|
||||||
Notifications.success('Node successfully removed', node.Name);
|
|
||||||
})
|
|
||||||
.catch(function error(err) {
|
|
||||||
Notifications.error('Failure', err, 'Unable to remove node');
|
|
||||||
})
|
|
||||||
.finally(function final() {
|
|
||||||
--actionCount;
|
|
||||||
if (actionCount === 0) {
|
|
||||||
$state.reload();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.cordonNodeAction = function(selectedItems) {
|
|
||||||
ModalService.confirm({
|
|
||||||
title: 'Are you sure?',
|
|
||||||
message: 'Do you want really want to put the nodes in maintenance mode?',
|
|
||||||
buttons: {
|
|
||||||
confirm: {
|
|
||||||
label: 'Cordon',
|
|
||||||
className: 'btn-danger'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
callback: function onConfirm(confirmed) {
|
|
||||||
if(!confirmed) { return; }
|
|
||||||
cordonNode(selectedItems);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function cordonNode(selectedItems) {
|
|
||||||
var actionCount = selectedItems.length;
|
|
||||||
angular.forEach(selectedItems, function (node) {
|
|
||||||
StoridgeNodeService.cordon(node.Name)
|
|
||||||
.then(function success() {
|
|
||||||
Notifications.success('Node successfully put in maintenance', node.Name);
|
|
||||||
})
|
|
||||||
.catch(function error(err) {
|
|
||||||
Notifications.error('Failure', err, 'Unable to put node in maintenance mode');
|
|
||||||
})
|
|
||||||
.finally(function final() {
|
|
||||||
--actionCount;
|
|
||||||
if (actionCount === 0) {
|
|
||||||
$state.reload();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.uncordonNodeAction = function(selectedItems) {
|
|
||||||
ModalService.confirm({
|
|
||||||
title: 'Are you sure?',
|
|
||||||
message: 'Do you want really want to bring the nodes out of maintenance mode?',
|
|
||||||
buttons: {
|
|
||||||
confirm: {
|
|
||||||
label: 'Uncordon',
|
|
||||||
className: 'btn-danger'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
callback: function onConfirm(confirmed) {
|
|
||||||
if(!confirmed) { return; }
|
|
||||||
uncordonNode(selectedItems);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function uncordonNode(selectedItems) {
|
|
||||||
var actionCount = selectedItems.length;
|
|
||||||
angular.forEach(selectedItems, function (node) {
|
|
||||||
StoridgeNodeService.uncordon(node.Name)
|
|
||||||
.then(function success() {
|
|
||||||
Notifications.success('Node successfully bringed back', node.Name);
|
|
||||||
})
|
|
||||||
.catch(function error(err) {
|
|
||||||
Notifications.error('Failure', err, 'Unable to put node out of maintenance mode');
|
|
||||||
})
|
|
||||||
.finally(function final() {
|
|
||||||
--actionCount;
|
|
||||||
if (actionCount === 0) {
|
|
||||||
$state.reload();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.rebootCluster = function() {
|
$scope.rebootCluster = function() {
|
||||||
ModalService.confirm({
|
ModalService.confirm({
|
||||||
title: 'Are you sure?',
|
title: 'Are you sure?',
|
||||||
|
@ -179,14 +65,12 @@ function ($q, $scope, $state, clipboard, Notifications, StoridgeClusterService,
|
||||||
$q.all({
|
$q.all({
|
||||||
info: StoridgeClusterService.info(),
|
info: StoridgeClusterService.info(),
|
||||||
version: StoridgeClusterService.version(),
|
version: StoridgeClusterService.version(),
|
||||||
nodes: StoridgeNodeService.nodes(),
|
nodes: StoridgeNodeService.nodes()
|
||||||
addInfo: StoridgeNodeService.add()
|
|
||||||
})
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
$scope.clusterInfo = data.info;
|
$scope.clusterInfo = data.info;
|
||||||
$scope.clusterVersion = data.version;
|
$scope.clusterVersion = data.version;
|
||||||
$scope.clusterNodes = data.nodes;
|
$scope.clusterNodes = data.nodes;
|
||||||
$scope.addInfo = data.addInfo.content;
|
|
||||||
})
|
})
|
||||||
.catch(function error(err) {
|
.catch(function error(err) {
|
||||||
Notifications.error('Failure', err, 'Unable to retrieve cluster information');
|
Notifications.error('Failure', err, 'Unable to retrieve cluster information');
|
||||||
|
|
|
@ -9,7 +9,19 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12 col-md-12 col-xs-12">
|
<div class="col-lg-12 col-md-12 col-xs-12">
|
||||||
<rd-widget>
|
<rd-widget>
|
||||||
<rd-widget-header icon="fa-object-group" title-text="Node details"></rd-widget-header>
|
<rd-widget-header icon="fa-object-group" title-text="Node details">
|
||||||
|
<button type="button" class="btn btn-sm btn-danger" ng-click="removeNodeAction()">
|
||||||
|
<i class="fa fa-trash-alt space-right" aria-hidden="true"></i>Remove node
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-primary"
|
||||||
|
ng-disabled="node.Status === 'maintenance'" ng-click="cordonNodeAction()">
|
||||||
|
<i class="fas fa-wrench space-right" aria-hidden="true"></i>Enter maintenance mode
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-primary"
|
||||||
|
ng-disabled="node.Status !== 'maintenance'" ng-click="uncordonNodeAction()">
|
||||||
|
<i class="fa fa-power-off space-right" aria-hidden="true"></i>Exit maintenance mode
|
||||||
|
</button>
|
||||||
|
</rd-widget-header>
|
||||||
<rd-widget-body classes="no-padding">
|
<rd-widget-body classes="no-padding">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
|
@ -1,7 +1,88 @@
|
||||||
angular.module('extension.storidge')
|
angular.module('extension.storidge')
|
||||||
.controller('StoridgeNodeController', ['$scope', '$state', '$transition$', 'Notifications', 'StoridgeNodeService',
|
.controller('StoridgeNodeController', ['$scope', '$state', '$transition$', 'Notifications', 'StoridgeNodeService', 'ModalService',
|
||||||
function ($scope, $state, $transition$, Notifications, StoridgeNodeService) {
|
function ($scope, $state, $transition$, Notifications, StoridgeNodeService, ModalService) {
|
||||||
|
|
||||||
|
$scope.removeNodeAction = function(selectedItems) {
|
||||||
|
ModalService.confirm({
|
||||||
|
title: 'Are you sure?',
|
||||||
|
message: 'Do you want really want to remove the node from the cluster?',
|
||||||
|
buttons: {
|
||||||
|
confirm: {
|
||||||
|
label: 'Remove',
|
||||||
|
className: 'btn-danger'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callback: function onConfirm(confirmed) {
|
||||||
|
if(!confirmed) { return; }
|
||||||
|
remove(selectedItems);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function remove() {
|
||||||
|
StoridgeNodeService.remove($scope.node.Name)
|
||||||
|
.then(function success() {
|
||||||
|
Notifications.success('Node successfully removed', $scope.node.Name);
|
||||||
|
$state.go('storidge.cluster');
|
||||||
|
})
|
||||||
|
.catch(function error(err) {
|
||||||
|
Notifications.error('Failure', err, 'Unable to remove node');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.cordonNodeAction = function(selectedItems) {
|
||||||
|
ModalService.confirm({
|
||||||
|
title: 'Are you sure?',
|
||||||
|
message: 'Do you want really want to put the node in maintenance mode?',
|
||||||
|
buttons: {
|
||||||
|
confirm: {
|
||||||
|
label: 'Enter maintenance',
|
||||||
|
className: 'btn-danger'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callback: function onConfirm(confirmed) {
|
||||||
|
if(!confirmed) { return; }
|
||||||
|
cordonNode(selectedItems);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function cordonNode() {
|
||||||
|
StoridgeNodeService.cordon($scope.node.Name)
|
||||||
|
.then(function success() {
|
||||||
|
Notifications.success('Node successfully put in maintenance');
|
||||||
|
})
|
||||||
|
.catch(function error(err) {
|
||||||
|
Notifications.error('Failure', err, 'Unable to put node in maintenance mode');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.uncordonNodeAction = function(selectedItems) {
|
||||||
|
ModalService.confirm({
|
||||||
|
title: 'Are you sure?',
|
||||||
|
message: 'Do you want really want to bring the nodes out of maintenance mode?',
|
||||||
|
buttons: {
|
||||||
|
confirm: {
|
||||||
|
label: 'Exit maintenance',
|
||||||
|
className: 'btn-danger'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
callback: function onConfirm(confirmed) {
|
||||||
|
if(!confirmed) { return; }
|
||||||
|
uncordonNode(selectedItems);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function uncordonNode() {
|
||||||
|
StoridgeNodeService.uncordon($scope.node.Name)
|
||||||
|
.then(function success() {
|
||||||
|
Notifications.success('Node successfully bringed back');
|
||||||
|
})
|
||||||
|
.catch(function error(err) {
|
||||||
|
Notifications.error('Failure', err, 'Unable to put node out of maintenance mode');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function initView() {
|
function initView() {
|
||||||
$scope.name = $transition$.params().name;
|
$scope.name = $transition$.params().name;
|
||||||
|
|
|
@ -17,6 +17,8 @@ angular.module('portainer.app')
|
||||||
msg = e.data.details;
|
msg = e.data.details;
|
||||||
} else if (e.data && e.data.message) {
|
} else if (e.data && e.data.message) {
|
||||||
msg = e.data.message;
|
msg = e.data.message;
|
||||||
|
} else if (e.data && e.data.content) {
|
||||||
|
msg = e.data.content;
|
||||||
} else if (e.message) {
|
} else if (e.message) {
|
||||||
msg = e.message;
|
msg = e.message;
|
||||||
} else if (e.err && e.err.data && e.err.data.message) {
|
} else if (e.err && e.err.data && e.err.data.message) {
|
||||||
|
|
Loading…
Reference in New Issue