mirror of https://github.com/portainer/portainer
feat(home): add the ability to refresh endpoint information (#2080)
* feat(home): add the ability to refresh endpoint information * style(home): update refresh confirmation messagepull/2073/head
parent
52f71b0813
commit
ab77f149fa
|
@ -0,0 +1,42 @@
|
|||
package endpoints
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/portainer/portainer"
|
||||
httperror "github.com/portainer/portainer/http/error"
|
||||
"github.com/portainer/portainer/http/response"
|
||||
)
|
||||
|
||||
// POST request on /api/endpoints/snapshot
|
||||
func (handler *Handler) endpointSnapshot(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpoints, err := handler.EndpointService.Endpoints()
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve endpoints from the database", err}
|
||||
}
|
||||
|
||||
for _, endpoint := range endpoints {
|
||||
if endpoint.Type == portainer.AzureEnvironment {
|
||||
continue
|
||||
}
|
||||
|
||||
snapshot, err := handler.Snapshotter.CreateSnapshot(&endpoint)
|
||||
endpoint.Status = portainer.EndpointStatusUp
|
||||
if err != nil {
|
||||
log.Printf("http error: endpoint snapshot error (endpoint=%s, URL=%s) (err=%s)\n", endpoint.Name, endpoint.URL, err)
|
||||
endpoint.Status = portainer.EndpointStatusDown
|
||||
}
|
||||
|
||||
if snapshot != nil {
|
||||
endpoint.Snapshots = []portainer.Snapshot{*snapshot}
|
||||
}
|
||||
|
||||
err = handler.EndpointService.UpdateEndpoint(endpoint.ID, &endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist endpoint changes inside the database", err}
|
||||
}
|
||||
}
|
||||
|
||||
return response.Empty(w)
|
||||
}
|
|
@ -43,6 +43,8 @@ func NewHandler(bouncer *security.RequestBouncer, authorizeEndpointManagement bo
|
|||
|
||||
h.Handle("/endpoints",
|
||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointCreate))).Methods(http.MethodPost)
|
||||
h.Handle("/endpoints/snapshot",
|
||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointSnapshot))).Methods(http.MethodPost)
|
||||
h.Handle("/endpoints",
|
||||
bouncer.RestrictedAccess(httperror.LoggerHandler(h.endpointList))).Methods(http.MethodGet)
|
||||
h.Handle("/endpoints/{id}",
|
||||
|
|
|
@ -11,6 +11,8 @@ angular.module('portainer.app').component('endpointList', {
|
|||
titleText: '@',
|
||||
titleIcon: '@',
|
||||
endpoints: '<',
|
||||
dashboardAction: '<'
|
||||
dashboardAction: '<',
|
||||
snapshotAction: '<',
|
||||
showSnapshotAction: '<'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="actionBar" ng-if="$ctrl.showSnapshotAction">
|
||||
<button type="button" class="btn btn-sm btn-primary" ng-click="$ctrl.snapshotAction()">
|
||||
<i class="fa fa-sync space-right" aria-hidden="true"></i>Refresh
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="searchBar">
|
||||
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
|
||||
<input type="text" class="searchInput" ng-model="$ctrl.state.textFilter" placeholder="Search by name, group, tag..." auto-focus>
|
||||
|
|
|
@ -6,6 +6,7 @@ angular.module('portainer.app')
|
|||
get: { method: 'GET', params: { id: '@id' } },
|
||||
update: { method: 'PUT', params: { id: '@id' } },
|
||||
updateAccess: { method: 'PUT', params: { id: '@id', action: 'access' } },
|
||||
remove: { method: 'DELETE', params: { id: '@id'} }
|
||||
remove: { method: 'DELETE', params: { id: '@id'} },
|
||||
snapshot: { method: 'POST', params: { id: 'snapshot' }}
|
||||
});
|
||||
}]);
|
||||
|
|
|
@ -12,6 +12,10 @@ function EndpointServiceFactory($q, Endpoints, FileUploadService) {
|
|||
return Endpoints.query({}).$promise;
|
||||
};
|
||||
|
||||
service.snapshot = function() {
|
||||
return Endpoints.snapshot({}, {}).$promise;
|
||||
};
|
||||
|
||||
service.endpointsByGroup = function(groupId) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
|
|
|
@ -142,14 +142,14 @@ angular.module('portainer.app')
|
|||
}, false);
|
||||
};
|
||||
|
||||
service.confirmExperimentalFeature = function(callback) {
|
||||
service.confirmEndpointSnapshot = function(callback) {
|
||||
service.confirm({
|
||||
title: 'Experimental feature',
|
||||
message: 'This feature is currently experimental, please use with caution.',
|
||||
title: 'Are you sure?',
|
||||
message: 'Triggering a manual refresh will poll each endpoint to retrieve its information, this may take a few moments.',
|
||||
buttons: {
|
||||
confirm: {
|
||||
label: 'Continue',
|
||||
className: 'btn-danger'
|
||||
className: 'btn-primary'
|
||||
}
|
||||
},
|
||||
callback: callback
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
title-text="Endpoints" title-icon="fa-plug"
|
||||
endpoints="endpoints"
|
||||
dashboard-action="goToDashboard"
|
||||
show-snapshot-action="isAdmin"
|
||||
snapshot-action="triggerSnapshot"
|
||||
></endpoint-list>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
angular.module('portainer.app')
|
||||
.controller('HomeController', ['$q', '$scope', '$state', 'Authentication', 'EndpointService', 'EndpointHelper', 'GroupService', 'Notifications', 'EndpointProvider', 'StateManager', 'ExtensionManager',
|
||||
function ($q, $scope, $state, Authentication, EndpointService, EndpointHelper, GroupService, Notifications, EndpointProvider, StateManager, ExtensionManager) {
|
||||
.controller('HomeController', ['$q', '$scope', '$state', 'Authentication', 'EndpointService', 'EndpointHelper', 'GroupService', 'Notifications', 'EndpointProvider', 'StateManager', 'ExtensionManager', 'ModalService',
|
||||
function ($q, $scope, $state, Authentication, EndpointService, EndpointHelper, GroupService, Notifications, EndpointProvider, StateManager, ExtensionManager, ModalService) {
|
||||
|
||||
$scope.goToDashboard = function(endpoint) {
|
||||
EndpointProvider.setEndpointID(endpoint.Id);
|
||||
|
@ -12,6 +12,24 @@ function ($q, $scope, $state, Authentication, EndpointService, EndpointHelper, G
|
|||
}
|
||||
};
|
||||
|
||||
function triggerSnapshot() {
|
||||
EndpointService.snapshot()
|
||||
.then(function success(data) {
|
||||
Notifications.success('Success', 'Endpoints updated');
|
||||
$state.reload();
|
||||
})
|
||||
.catch(function error(err) {
|
||||
Notifications.error('Failure', err, 'An error occured during endpoint snapshot');
|
||||
});
|
||||
}
|
||||
|
||||
$scope.triggerSnapshot = function() {
|
||||
ModalService.confirmEndpointSnapshot(function (result) {
|
||||
if(!result) { return; }
|
||||
triggerSnapshot();
|
||||
});
|
||||
};
|
||||
|
||||
function switchToAzureEndpoint(endpoint) {
|
||||
StateManager.updateEndpointState(endpoint.Name, endpoint.Type, [])
|
||||
.then(function success() {
|
||||
|
|
Loading…
Reference in New Issue