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",
|
h.Handle("/endpoints",
|
||||||
bouncer.AdministratorAccess(httperror.LoggerHandler(h.endpointCreate))).Methods(http.MethodPost)
|
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",
|
h.Handle("/endpoints",
|
||||||
bouncer.RestrictedAccess(httperror.LoggerHandler(h.endpointList))).Methods(http.MethodGet)
|
bouncer.RestrictedAccess(httperror.LoggerHandler(h.endpointList))).Methods(http.MethodGet)
|
||||||
h.Handle("/endpoints/{id}",
|
h.Handle("/endpoints/{id}",
|
||||||
|
|
|
@ -11,6 +11,8 @@ angular.module('portainer.app').component('endpointList', {
|
||||||
titleText: '@',
|
titleText: '@',
|
||||||
titleIcon: '@',
|
titleIcon: '@',
|
||||||
endpoints: '<',
|
endpoints: '<',
|
||||||
dashboardAction: '<'
|
dashboardAction: '<',
|
||||||
|
snapshotAction: '<',
|
||||||
|
showSnapshotAction: '<'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<div class="searchBar">
|
||||||
<i class="fa fa-search searchIcon" aria-hidden="true"></i>
|
<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>
|
<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' } },
|
get: { method: 'GET', params: { id: '@id' } },
|
||||||
update: { method: 'PUT', params: { id: '@id' } },
|
update: { method: 'PUT', params: { id: '@id' } },
|
||||||
updateAccess: { method: 'PUT', params: { id: '@id', action: 'access' } },
|
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;
|
return Endpoints.query({}).$promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
service.snapshot = function() {
|
||||||
|
return Endpoints.snapshot({}, {}).$promise;
|
||||||
|
};
|
||||||
|
|
||||||
service.endpointsByGroup = function(groupId) {
|
service.endpointsByGroup = function(groupId) {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
|
|
||||||
|
|
|
@ -142,14 +142,14 @@ angular.module('portainer.app')
|
||||||
}, false);
|
}, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
service.confirmExperimentalFeature = function(callback) {
|
service.confirmEndpointSnapshot = function(callback) {
|
||||||
service.confirm({
|
service.confirm({
|
||||||
title: 'Experimental feature',
|
title: 'Are you sure?',
|
||||||
message: 'This feature is currently experimental, please use with caution.',
|
message: 'Triggering a manual refresh will poll each endpoint to retrieve its information, this may take a few moments.',
|
||||||
buttons: {
|
buttons: {
|
||||||
confirm: {
|
confirm: {
|
||||||
label: 'Continue',
|
label: 'Continue',
|
||||||
className: 'btn-danger'
|
className: 'btn-primary'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
callback: callback
|
callback: callback
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
title-text="Endpoints" title-icon="fa-plug"
|
title-text="Endpoints" title-icon="fa-plug"
|
||||||
endpoints="endpoints"
|
endpoints="endpoints"
|
||||||
dashboard-action="goToDashboard"
|
dashboard-action="goToDashboard"
|
||||||
|
show-snapshot-action="isAdmin"
|
||||||
|
snapshot-action="triggerSnapshot"
|
||||||
></endpoint-list>
|
></endpoint-list>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
angular.module('portainer.app')
|
angular.module('portainer.app')
|
||||||
.controller('HomeController', ['$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) {
|
function ($q, $scope, $state, Authentication, EndpointService, EndpointHelper, GroupService, Notifications, EndpointProvider, StateManager, ExtensionManager, ModalService) {
|
||||||
|
|
||||||
$scope.goToDashboard = function(endpoint) {
|
$scope.goToDashboard = function(endpoint) {
|
||||||
EndpointProvider.setEndpointID(endpoint.Id);
|
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) {
|
function switchToAzureEndpoint(endpoint) {
|
||||||
StateManager.updateEndpointState(endpoint.Name, endpoint.Type, [])
|
StateManager.updateEndpointState(endpoint.Name, endpoint.Type, [])
|
||||||
.then(function success() {
|
.then(function success() {
|
||||||
|
|
Loading…
Reference in New Issue