mirror of https://github.com/portainer/portainer
feat(storidge): add extension check on endpoint switch (#1693)
* feat(storidge): add extension check on endpoint switch * feat(storidge): add extension check post loginpull/1707/head
parent
403de0d319
commit
f1a21c07bd
|
@ -33,6 +33,8 @@ func NewExtensionHandler(bouncer *security.RequestBouncer) *ExtensionHandler {
|
||||||
}
|
}
|
||||||
h.Handle("/{endpointId}/extensions",
|
h.Handle("/{endpointId}/extensions",
|
||||||
bouncer.AdministratorAccess(http.HandlerFunc(h.handlePostExtensions))).Methods(http.MethodPost)
|
bouncer.AdministratorAccess(http.HandlerFunc(h.handlePostExtensions))).Methods(http.MethodPost)
|
||||||
|
h.Handle("/{endpointId}/extensions/{extensionType}",
|
||||||
|
bouncer.AdministratorAccess(http.HandlerFunc(h.handleDeleteExtensions))).Methods(http.MethodDelete)
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,19 +77,23 @@ func (handler *ExtensionHandler) handlePostExtensions(w http.ResponseWriter, r *
|
||||||
|
|
||||||
extensionType := portainer.EndpointExtensionType(req.Type)
|
extensionType := portainer.EndpointExtensionType(req.Type)
|
||||||
|
|
||||||
for _, extension := range endpoint.Extensions {
|
var extension *portainer.EndpointExtension
|
||||||
if extension.Type == extensionType {
|
|
||||||
httperror.WriteErrorResponse(w, portainer.ErrEndpointExtensionAlreadyAssociated, http.StatusConflict, handler.Logger)
|
for _, ext := range endpoint.Extensions {
|
||||||
return
|
if ext.Type == extensionType {
|
||||||
|
extension = &ext
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension := portainer.EndpointExtension{
|
if extension != nil {
|
||||||
|
extension.URL = req.URL
|
||||||
|
} else {
|
||||||
|
extension = &portainer.EndpointExtension{
|
||||||
Type: extensionType,
|
Type: extensionType,
|
||||||
URL: req.URL,
|
URL: req.URL,
|
||||||
}
|
}
|
||||||
|
endpoint.Extensions = append(endpoint.Extensions, *extension)
|
||||||
endpoint.Extensions = append(endpoint.Extensions, extension)
|
}
|
||||||
|
|
||||||
err = handler.EndpointService.UpdateEndpoint(endpoint.ID, endpoint)
|
err = handler.EndpointService.UpdateEndpoint(endpoint.ID, endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -97,3 +103,41 @@ func (handler *ExtensionHandler) handlePostExtensions(w http.ResponseWriter, r *
|
||||||
|
|
||||||
encodeJSON(w, extension, handler.Logger)
|
encodeJSON(w, extension, handler.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (handler *ExtensionHandler) handleDeleteExtensions(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
id, err := strconv.Atoi(vars["endpointId"])
|
||||||
|
if err != nil {
|
||||||
|
httperror.WriteErrorResponse(w, err, http.StatusBadRequest, handler.Logger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
endpointID := portainer.EndpointID(id)
|
||||||
|
|
||||||
|
endpoint, err := handler.EndpointService.Endpoint(endpointID)
|
||||||
|
if err == portainer.ErrEndpointNotFound {
|
||||||
|
httperror.WriteErrorResponse(w, err, http.StatusNotFound, handler.Logger)
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
extType, err := strconv.Atoi(vars["extensionType"])
|
||||||
|
if err != nil {
|
||||||
|
httperror.WriteErrorResponse(w, err, http.StatusBadRequest, handler.Logger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
extensionType := portainer.EndpointExtensionType(extType)
|
||||||
|
|
||||||
|
for idx, ext := range endpoint.Extensions {
|
||||||
|
if ext.Type == extensionType {
|
||||||
|
endpoint.Extensions = append(endpoint.Extensions[:idx], endpoint.Extensions[idx+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = handler.EndpointService.UpdateEndpoint(endpoint.ID, endpoint)
|
||||||
|
if err != nil {
|
||||||
|
httperror.WriteErrorResponse(w, err, http.StatusInternalServerError, handler.Logger)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -44,7 +44,6 @@ function ($scope, $transition$, $interval, ServiceService, Notifications) {
|
||||||
ServiceService.logs($transition$.params().id, 1, 1, 0, $scope.state.lineCount)
|
ServiceService.logs($transition$.params().id, 1, 1, 0, $scope.state.lineCount)
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
$scope.logs = data;
|
$scope.logs = data;
|
||||||
console.log(JSON.stringify(data, null, 4));
|
|
||||||
setUpdateRepeater();
|
setUpdateRepeater();
|
||||||
})
|
})
|
||||||
.catch(function error(err) {
|
.catch(function error(err) {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
angular.module('portainer.app')
|
angular.module('portainer.app')
|
||||||
.factory('Extensions', ['$resource', 'EndpointProvider', 'API_ENDPOINT_ENDPOINTS', function Extensions($resource, EndpointProvider, API_ENDPOINT_ENDPOINTS) {
|
.factory('Extensions', ['$resource', 'EndpointProvider', 'API_ENDPOINT_ENDPOINTS', function Extensions($resource, EndpointProvider, API_ENDPOINT_ENDPOINTS) {
|
||||||
'use strict';
|
'use strict';
|
||||||
return $resource(API_ENDPOINT_ENDPOINTS + '/:endpointId/extensions', {
|
return $resource(API_ENDPOINT_ENDPOINTS + '/:endpointId/extensions/:type', {
|
||||||
endpointId: EndpointProvider.endpointID
|
endpointId: EndpointProvider.endpointID
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
register: { method: 'POST', params: { endpointId: '@endpointId' } }
|
register: { method: 'POST' },
|
||||||
|
deregister: { method: 'DELETE', params: { type: '@type' } }
|
||||||
});
|
});
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
angular.module('portainer.app')
|
angular.module('portainer.app')
|
||||||
.factory('EndpointService', ['$q', 'Endpoints', 'FileUploadService', function EndpointServiceFactory($q, Endpoints, FileUploadService) {
|
.factory('EndpointService', ['$q', 'Endpoints', 'FileUploadService',
|
||||||
|
function EndpointServiceFactory($q, Endpoints, FileUploadService) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var service = {};
|
var service = {};
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,8 @@ angular.module('portainer.app')
|
||||||
'use strict';
|
'use strict';
|
||||||
var service = {};
|
var service = {};
|
||||||
|
|
||||||
service.registerStoridgeExtension = function(endpointId, url) {
|
service.registerStoridgeExtension = function(url) {
|
||||||
var payload = {
|
var payload = {
|
||||||
endpointId: endpointId,
|
|
||||||
Type: 1,
|
Type: 1,
|
||||||
URL: url
|
URL: url
|
||||||
};
|
};
|
||||||
|
@ -13,5 +12,9 @@ angular.module('portainer.app')
|
||||||
return Extensions.register(payload).$promise;
|
return Extensions.register(payload).$promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
service.deregisterStoridgeExtension = function() {
|
||||||
|
return Extensions.deregister({ type: 1 }).$promise;
|
||||||
|
};
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -4,7 +4,7 @@ function ExtensionManagerFactory($q, PluginService, SystemService, ExtensionServ
|
||||||
'use strict';
|
'use strict';
|
||||||
var service = {};
|
var service = {};
|
||||||
|
|
||||||
service.initEndpointExtensions = function(endpointId) {
|
service.initEndpointExtensions = function() {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
|
|
||||||
SystemService.version()
|
SystemService.version()
|
||||||
|
@ -12,13 +12,11 @@ function ExtensionManagerFactory($q, PluginService, SystemService, ExtensionServ
|
||||||
var endpointAPIVersion = parseFloat(data.ApiVersion);
|
var endpointAPIVersion = parseFloat(data.ApiVersion);
|
||||||
|
|
||||||
return $q.all([
|
return $q.all([
|
||||||
endpointAPIVersion >= 1.25 ? initStoridgeExtension(endpointId): null
|
endpointAPIVersion >= 1.25 ? initStoridgeExtension(): null
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
var extensions = data.filter(function filterNull(x) {
|
var extensions = data;
|
||||||
return x;
|
|
||||||
});
|
|
||||||
deferred.resolve(extensions);
|
deferred.resolve(extensions);
|
||||||
})
|
})
|
||||||
.catch(function error(err) {
|
.catch(function error(err) {
|
||||||
|
@ -28,14 +26,16 @@ function ExtensionManagerFactory($q, PluginService, SystemService, ExtensionServ
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
function initStoridgeExtension(endpointId) {
|
function initStoridgeExtension() {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
|
|
||||||
PluginService.volumePlugins()
|
PluginService.volumePlugins()
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
var volumePlugins = data;
|
var volumePlugins = data;
|
||||||
if (_.includes(volumePlugins, 'cio:latest')) {
|
if (_.includes(volumePlugins, 'cio:latest')) {
|
||||||
return registerStoridgeUsingSwarmManagerIP(endpointId);
|
return registerStoridgeUsingSwarmManagerIP();
|
||||||
|
} else {
|
||||||
|
return deregisterStoridgeExtension();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
|
@ -48,14 +48,15 @@ function ExtensionManagerFactory($q, PluginService, SystemService, ExtensionServ
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerStoridgeUsingSwarmManagerIP(endpointId) {
|
function registerStoridgeUsingSwarmManagerIP() {
|
||||||
var deferred = $q.defer();
|
var deferred = $q.defer();
|
||||||
|
|
||||||
SystemService.info()
|
SystemService.info()
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
var managerIP = data.Swarm.NodeAddr;
|
var managerIP = data.Swarm.NodeAddr;
|
||||||
var storidgeAPIURL = 'tcp://' + managerIP + ':8282';
|
// var storidgeAPIURL = 'tcp://' + managerIP + ':8282';
|
||||||
return ExtensionService.registerStoridgeExtension(endpointId, storidgeAPIURL);
|
var storidgeAPIURL = 'tcp://home.cresswell.net.nz:8282';
|
||||||
|
return ExtensionService.registerStoridgeExtension(storidgeAPIURL);
|
||||||
})
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
deferred.resolve(data);
|
deferred.resolve(data);
|
||||||
|
@ -67,5 +68,9 @@ function ExtensionManagerFactory($q, PluginService, SystemService, ExtensionServ
|
||||||
return deferred.promise;
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deregisterStoridgeExtension() {
|
||||||
|
return ExtensionService.deregisterStoridgeExtension();
|
||||||
|
}
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
}]);
|
}]);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
angular.module('portainer.app')
|
angular.module('portainer.app')
|
||||||
.controller('AuthenticationController', ['$scope', '$state', '$transition$', '$window', '$timeout', '$sanitize', 'Authentication', 'Users', 'UserService', 'EndpointService', 'StateManager', 'EndpointProvider', 'Notifications', 'SettingsService',
|
.controller('AuthenticationController', ['$scope', '$state', '$transition$', '$window', '$timeout', '$sanitize', 'Authentication', 'Users', 'UserService', 'EndpointService', 'StateManager', 'EndpointProvider', 'Notifications', 'SettingsService', 'ExtensionManager',
|
||||||
function ($scope, $state, $transition$, $window, $timeout, $sanitize, Authentication, Users, UserService, EndpointService, StateManager, EndpointProvider, Notifications, SettingsService) {
|
function ($scope, $state, $transition$, $window, $timeout, $sanitize, Authentication, Users, UserService, EndpointService, StateManager, EndpointProvider, Notifications, SettingsService, ExtensionManager) {
|
||||||
|
|
||||||
$scope.logo = StateManager.getState().application.logo;
|
$scope.logo = StateManager.getState().application.logo;
|
||||||
|
|
||||||
|
@ -18,7 +18,12 @@ function ($scope, $state, $transition$, $window, $timeout, $sanitize, Authentica
|
||||||
if (!endpointID) {
|
if (!endpointID) {
|
||||||
EndpointProvider.setEndpointID(endpoint.Id);
|
EndpointProvider.setEndpointID(endpoint.Id);
|
||||||
}
|
}
|
||||||
StateManager.updateEndpointState(true, endpoint.Extensions)
|
|
||||||
|
ExtensionManager.initEndpointExtensions(endpoint.Id)
|
||||||
|
.then(function success(data) {
|
||||||
|
var extensions = data;
|
||||||
|
return StateManager.updateEndpointState(true, extensions);
|
||||||
|
})
|
||||||
.then(function success(data) {
|
.then(function success(data) {
|
||||||
$state.go('docker.dashboard');
|
$state.go('docker.dashboard');
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
angular.module('portainer.app')
|
angular.module('portainer.app')
|
||||||
.controller('EndpointsController', ['$scope', '$state', '$filter', 'EndpointService', 'Notifications', 'ExtensionManager', 'EndpointProvider',
|
.controller('EndpointsController', ['$scope', '$state', '$filter', 'EndpointService', 'Notifications', 'SystemService', 'EndpointProvider',
|
||||||
function ($scope, $state, $filter, EndpointService, Notifications, ExtensionManager, EndpointProvider) {
|
function ($scope, $state, $filter, EndpointService, Notifications, SystemService, EndpointProvider) {
|
||||||
$scope.state = {
|
$scope.state = {
|
||||||
uploadInProgress: false,
|
uploadInProgress: false,
|
||||||
actionInProgress: false
|
actionInProgress: false
|
||||||
|
@ -37,8 +37,8 @@ function ($scope, $state, $filter, EndpointService, Notifications, ExtensionMana
|
||||||
endpointId = data.Id;
|
endpointId = data.Id;
|
||||||
var currentEndpointId = EndpointProvider.endpointID();
|
var currentEndpointId = EndpointProvider.endpointID();
|
||||||
EndpointProvider.setEndpointID(endpointId);
|
EndpointProvider.setEndpointID(endpointId);
|
||||||
ExtensionManager.initEndpointExtensions(endpointId)
|
SystemService.info()
|
||||||
.then(function success(data) {
|
.then(function success() {
|
||||||
Notifications.success('Endpoint created', name);
|
Notifications.success('Endpoint created', name);
|
||||||
$state.reload();
|
$state.reload();
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
angular.module('portainer.app')
|
angular.module('portainer.app')
|
||||||
.controller('SidebarController', ['$q', '$scope', '$state', 'Settings', 'EndpointService', 'StateManager', 'EndpointProvider', 'Notifications', 'Authentication', 'UserService',
|
.controller('SidebarController', ['$q', '$scope', '$state', 'Settings', 'EndpointService', 'StateManager', 'EndpointProvider', 'Notifications', 'Authentication', 'UserService', 'ExtensionManager',
|
||||||
function ($q, $scope, $state, Settings, EndpointService, StateManager, EndpointProvider, Notifications, Authentication, UserService) {
|
function ($q, $scope, $state, Settings, EndpointService, StateManager, EndpointProvider, Notifications, Authentication, UserService, ExtensionManager) {
|
||||||
|
|
||||||
$scope.switchEndpoint = function(endpoint) {
|
$scope.switchEndpoint = function(endpoint) {
|
||||||
var activeEndpointID = EndpointProvider.endpointID();
|
var activeEndpointID = EndpointProvider.endpointID();
|
||||||
|
@ -8,7 +8,11 @@ function ($q, $scope, $state, Settings, EndpointService, StateManager, EndpointP
|
||||||
EndpointProvider.setEndpointID(endpoint.Id);
|
EndpointProvider.setEndpointID(endpoint.Id);
|
||||||
EndpointProvider.setEndpointPublicURL(endpoint.PublicURL);
|
EndpointProvider.setEndpointPublicURL(endpoint.PublicURL);
|
||||||
|
|
||||||
StateManager.updateEndpointState(true, endpoint.Extensions)
|
ExtensionManager.initEndpointExtensions(endpoint.Id)
|
||||||
|
.then(function success(data) {
|
||||||
|
var extensions = data;
|
||||||
|
return StateManager.updateEndpointState(true, extensions);
|
||||||
|
})
|
||||||
.then(function success() {
|
.then(function success() {
|
||||||
$state.go('docker.dashboard');
|
$state.go('docker.dashboard');
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue