mirror of
https://github.com/portainer/portainer.git
synced 2025-08-08 07:15:23 +02:00
refactor(environments): remove endpoints cache [DTD-100] (#6408)
This commit is contained in:
parent
9ef2e27aae
commit
37d4a80769
51 changed files with 155 additions and 353 deletions
|
@ -1,45 +0,0 @@
|
|||
import _ from 'lodash-es';
|
||||
|
||||
angular.module('portainer.app').factory('EndpointStatusInterceptor', [
|
||||
'$q',
|
||||
'EndpointProvider',
|
||||
function ($q, EndpointProvider) {
|
||||
'use strict';
|
||||
var interceptor = {};
|
||||
|
||||
interceptor.response = responseInterceptor;
|
||||
interceptor.responseError = responseErrorInterceptor;
|
||||
|
||||
function canBeOffline(url) {
|
||||
return (
|
||||
_.startsWith(url, 'api/') &&
|
||||
(_.includes(url, '/containers') ||
|
||||
_.includes(url, '/images') ||
|
||||
_.includes(url, '/volumes') ||
|
||||
_.includes(url, '/networks') ||
|
||||
_.includes(url, '/info') ||
|
||||
_.includes(url, '/version'))
|
||||
);
|
||||
}
|
||||
|
||||
function responseInterceptor(response) {
|
||||
var url = response.config.url;
|
||||
if (response.status === 200 && canBeOffline(url) && EndpointProvider.offlineMode()) {
|
||||
EndpointProvider.setOfflineMode(false);
|
||||
}
|
||||
return response || $q.when(response);
|
||||
}
|
||||
|
||||
function responseErrorInterceptor(rejection) {
|
||||
if (rejection.config) {
|
||||
var url = rejection.config.url;
|
||||
if ((rejection.status === 502 || rejection.status === 503 || rejection.status === -1) && canBeOffline(url) && !EndpointProvider.offlineMode()) {
|
||||
EndpointProvider.setOfflineMode(true);
|
||||
}
|
||||
}
|
||||
return $q.reject(rejection);
|
||||
}
|
||||
|
||||
return interceptor;
|
||||
},
|
||||
]);
|
|
@ -11,8 +11,7 @@ angular.module('portainer.app').factory('StackService', [
|
|||
'ServiceService',
|
||||
'ContainerService',
|
||||
'SwarmService',
|
||||
'EndpointProvider',
|
||||
function StackServiceFactory($q, $async, Stack, FileUploadService, StackHelper, ServiceService, ContainerService, SwarmService, EndpointProvider) {
|
||||
function StackServiceFactory($q, $async, Stack, FileUploadService, StackHelper, ServiceService, ContainerService, SwarmService) {
|
||||
'use strict';
|
||||
var service = {
|
||||
updateGit,
|
||||
|
@ -51,8 +50,6 @@ angular.module('portainer.app').factory('StackService', [
|
|||
service.migrateSwarmStack = function (stack, targetEndpointId, newName) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
EndpointProvider.setEndpointID(targetEndpointId);
|
||||
|
||||
SwarmService.swarm()
|
||||
.then(function success(data) {
|
||||
var swarm = data;
|
||||
|
@ -67,9 +64,6 @@ angular.module('portainer.app').factory('StackService', [
|
|||
})
|
||||
.catch(function error(err) {
|
||||
deferred.reject({ msg: 'Unable to migrate stack', err: err });
|
||||
})
|
||||
.finally(function final() {
|
||||
EndpointProvider.setEndpointID(stack.EndpointId);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
|
@ -78,14 +72,11 @@ angular.module('portainer.app').factory('StackService', [
|
|||
service.migrateComposeStack = function (stack, targetEndpointId, newName) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
EndpointProvider.setEndpointID(targetEndpointId);
|
||||
|
||||
Stack.migrate({ id: stack.Id, endpointId: stack.EndpointId }, { EndpointID: targetEndpointId, Name: newName })
|
||||
.$promise.then(function success() {
|
||||
deferred.resolve();
|
||||
})
|
||||
.catch(function error(err) {
|
||||
EndpointProvider.setEndpointID(stack.EndpointId);
|
||||
deferred.reject({ msg: 'Unable to migrate stack', err: err });
|
||||
});
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ const DEFAULT_PASSWORD = 'K7yJPP5qNK4hf1QsRnfV';
|
|||
|
||||
angular.module('portainer.app').factory('Authentication', [
|
||||
'$async',
|
||||
'$state',
|
||||
'Auth',
|
||||
'OAuth',
|
||||
'jwtHelper',
|
||||
|
@ -14,7 +13,7 @@ angular.module('portainer.app').factory('Authentication', [
|
|||
'EndpointProvider',
|
||||
'UserService',
|
||||
'ThemeManager',
|
||||
function AuthenticationFactory($async, $state, Auth, OAuth, jwtHelper, LocalStorage, StateManager, EndpointProvider, UserService, ThemeManager) {
|
||||
function AuthenticationFactory($async, Auth, OAuth, jwtHelper, LocalStorage, StateManager, EndpointProvider, UserService, ThemeManager) {
|
||||
'use strict';
|
||||
|
||||
var service = {};
|
||||
|
@ -50,7 +49,6 @@ angular.module('portainer.app').factory('Authentication', [
|
|||
clearSessionStorage();
|
||||
StateManager.clean();
|
||||
EndpointProvider.clean();
|
||||
EndpointProvider.setCurrentEndpoint(null);
|
||||
LocalStorage.cleanAuthData();
|
||||
LocalStorage.storeLoginStateUUID('');
|
||||
tryAutoLoginExtension();
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
angular.module('portainer.app').factory(
|
||||
'EndpointProvider',
|
||||
/* @ngInject */
|
||||
function EndpointProviderFactory(LocalStorage, $uiRouterGlobals) {
|
||||
const state = {
|
||||
currentEndpoint: null,
|
||||
};
|
||||
var service = {};
|
||||
var endpoint = {};
|
||||
|
||||
service.initialize = function () {
|
||||
var endpointID = LocalStorage.getEndpointID();
|
||||
var endpointPublicURL = LocalStorage.getEndpointPublicURL();
|
||||
var offlineMode = LocalStorage.getOfflineMode();
|
||||
|
||||
if (endpointID) {
|
||||
endpoint.ID = endpointID;
|
||||
}
|
||||
if (endpointPublicURL) {
|
||||
endpoint.PublicURL = endpointPublicURL;
|
||||
}
|
||||
if (offlineMode) {
|
||||
endpoint.OfflineMode = offlineMode;
|
||||
}
|
||||
};
|
||||
|
||||
service.clean = function () {
|
||||
LocalStorage.cleanEndpointData();
|
||||
endpoint = {};
|
||||
};
|
||||
|
||||
service.endpoint = function () {
|
||||
return endpoint;
|
||||
};
|
||||
|
||||
service.endpointID = function () {
|
||||
if (endpoint.ID === undefined) {
|
||||
endpoint.ID = LocalStorage.getEndpointID();
|
||||
}
|
||||
if (endpoint.ID === null || endpoint.ID === undefined) {
|
||||
return service.getUrlEndpointID();
|
||||
}
|
||||
return endpoint.ID;
|
||||
};
|
||||
|
||||
// TODO: technical debt
|
||||
// Reference issue: JIRA CE-463
|
||||
// Documentation (https://ui-router.github.io/ng1/docs/latest/modules/injectables.html) show the usage of either
|
||||
// * $stateParams
|
||||
// * $transition$
|
||||
// * $uiRouterGlobals
|
||||
// to retrieve the URL params
|
||||
//
|
||||
// * $stateParams: is deprecated and will cause a circular dependency injection error
|
||||
// because EndpointProvider is used by EndpointStatusInterceptor which is injected inside $httpProvider
|
||||
// >> [$injector:cdep] Circular dependency found: $uiRouter <- $stateParams <- EndpointProvider <- EndpointStatusInterceptor <- $http <- $uiRouter
|
||||
// For more details, see https://stackoverflow.com/questions/20230691/injecting-state-ui-router-into-http-interceptor-causes-circular-dependency#20230786
|
||||
//
|
||||
// * $transition$: mentionned as the replacement of $stateParams (https://ui-router.github.io/guide/ng1/migrate-to-1_0#stateparams-deprecation)
|
||||
// but is not injectable without tweaks inside a service
|
||||
//
|
||||
// * $uiRouterGlobal: per https://github.com/angular-ui/ui-router/issues/3237#issuecomment-271979688
|
||||
// seems the recommanded way to retrieve params inside a service/factory
|
||||
//
|
||||
// We need this function to fallback on URL endpoint ID when no endpoint has been selected
|
||||
service.getUrlEndpointID = () => {
|
||||
return $uiRouterGlobals.params.id;
|
||||
};
|
||||
|
||||
service.setEndpointID = function (id) {
|
||||
endpoint.ID = id;
|
||||
LocalStorage.storeEndpointID(id);
|
||||
};
|
||||
|
||||
service.endpointPublicURL = function () {
|
||||
if (endpoint.PublicURL === undefined) {
|
||||
endpoint.PublicURL = LocalStorage.getEndpointPublicURL();
|
||||
}
|
||||
return endpoint.PublicURL;
|
||||
};
|
||||
|
||||
service.setEndpointPublicURL = function (publicURL) {
|
||||
endpoint.PublicURL = publicURL;
|
||||
LocalStorage.storeEndpointPublicURL(publicURL);
|
||||
};
|
||||
|
||||
service.endpoints = function () {
|
||||
return LocalStorage.getEndpoints();
|
||||
};
|
||||
|
||||
service.setEndpoints = function (data) {
|
||||
LocalStorage.storeEndpoints(data);
|
||||
};
|
||||
|
||||
service.offlineMode = function () {
|
||||
return endpoint.OfflineMode;
|
||||
};
|
||||
|
||||
service.setOfflineMode = function (isOffline) {
|
||||
endpoint.OfflineMode = isOffline;
|
||||
LocalStorage.storeOfflineMode(isOffline);
|
||||
};
|
||||
|
||||
service.setOfflineModeFromStatus = function (status) {
|
||||
var isOffline = status !== 1;
|
||||
endpoint.OfflineMode = isOffline;
|
||||
LocalStorage.storeOfflineMode(isOffline);
|
||||
};
|
||||
|
||||
service.currentEndpoint = function () {
|
||||
return state.currentEndpoint;
|
||||
};
|
||||
|
||||
service.setCurrentEndpoint = function (endpoint) {
|
||||
state.currentEndpoint = endpoint;
|
||||
};
|
||||
|
||||
return service;
|
||||
}
|
||||
);
|
47
app/portainer/services/endpointProvider.ts
Normal file
47
app/portainer/services/endpointProvider.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { ping } from '@/docker/services/ping';
|
||||
import {
|
||||
Environment,
|
||||
EnvironmentType,
|
||||
} from '@/react/portainer/environments/types';
|
||||
|
||||
interface State {
|
||||
currentEndpoint: Environment | null;
|
||||
pingInterval: NodeJS.Timer | null;
|
||||
}
|
||||
|
||||
/* @ngInject */
|
||||
export function EndpointProvider() {
|
||||
const state: State = {
|
||||
currentEndpoint: null,
|
||||
pingInterval: null,
|
||||
};
|
||||
|
||||
return { endpointID, setCurrentEndpoint, currentEndpoint, clean };
|
||||
|
||||
function endpointID() {
|
||||
return state.currentEndpoint?.Id;
|
||||
}
|
||||
|
||||
function setCurrentEndpoint(endpoint: Environment | null) {
|
||||
state.currentEndpoint = endpoint;
|
||||
|
||||
if (state.pingInterval) {
|
||||
clearInterval(state.pingInterval);
|
||||
state.pingInterval = null;
|
||||
}
|
||||
|
||||
if (endpoint && endpoint.Type === EnvironmentType.EdgeAgentOnDocker) {
|
||||
state.pingInterval = setInterval(() => ping(endpoint.Id), 60 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
function currentEndpoint() {
|
||||
return state.currentEndpoint;
|
||||
}
|
||||
|
||||
function clean() {
|
||||
setCurrentEndpoint(null);
|
||||
}
|
||||
}
|
||||
|
||||
export type EndpointProviderInterface = ReturnType<typeof EndpointProvider>;
|
|
@ -4,9 +4,11 @@ import { apiServicesModule } from './api';
|
|||
import { Notifications } from './notifications';
|
||||
import { ModalServiceAngular } from './modal.service';
|
||||
import { HttpRequestHelperAngular } from './http-request.helper';
|
||||
import { EndpointProvider } from './endpointProvider';
|
||||
|
||||
export default angular
|
||||
.module('portainer.app.services', [apiServicesModule])
|
||||
.factory('Notifications', Notifications)
|
||||
.factory('ModalService', ModalServiceAngular)
|
||||
.factory('EndpointProvider', EndpointProvider)
|
||||
.factory('HttpRequestHelper', HttpRequestHelperAngular).name;
|
||||
|
|
|
@ -2,42 +2,21 @@ angular.module('portainer.app').factory('LocalStorage', [
|
|||
'localStorageService',
|
||||
function LocalStorageFactory(localStorageService) {
|
||||
return {
|
||||
storeEndpointID: function (id) {
|
||||
localStorageService.set('ENDPOINT_ID', id);
|
||||
},
|
||||
getEndpointID: function () {
|
||||
return localStorageService.get('ENDPOINT_ID');
|
||||
},
|
||||
storeEndpointPublicURL: function (publicURL) {
|
||||
localStorageService.set('ENDPOINT_PUBLIC_URL', publicURL);
|
||||
},
|
||||
getEndpointPublicURL: function () {
|
||||
return localStorageService.get('ENDPOINT_PUBLIC_URL');
|
||||
},
|
||||
storeLoginStateUUID: function (uuid) {
|
||||
localStorageService.set('LOGIN_STATE_UUID', uuid);
|
||||
},
|
||||
getLoginStateUUID: function () {
|
||||
return localStorageService.get('LOGIN_STATE_UUID');
|
||||
},
|
||||
storeOfflineMode: function (isOffline) {
|
||||
localStorageService.set('ENDPOINT_OFFLINE_MODE', isOffline);
|
||||
},
|
||||
getOfflineMode: function () {
|
||||
return localStorageService.get('ENDPOINT_OFFLINE_MODE');
|
||||
},
|
||||
storeEndpoints: function (data) {
|
||||
localStorageService.set('ENDPOINTS_DATA', data);
|
||||
},
|
||||
getEndpoints: function () {
|
||||
return localStorageService.get('ENDPOINTS_DATA');
|
||||
},
|
||||
storeEndpointState: function (state) {
|
||||
localStorageService.set('ENDPOINT_STATE', state);
|
||||
},
|
||||
getEndpointState: function () {
|
||||
return localStorageService.get('ENDPOINT_STATE');
|
||||
},
|
||||
cleanEndpointState() {
|
||||
localStorageService.remove('ENDPOINT_STATE');
|
||||
},
|
||||
storeApplicationState: function (state) {
|
||||
localStorageService.set('APPLICATION_STATE', state);
|
||||
},
|
||||
|
@ -135,9 +114,6 @@ angular.module('portainer.app').factory('LocalStorage', [
|
|||
cleanAuthData() {
|
||||
localStorageService.remove('JWT', 'APPLICATION_STATE', 'LOGIN_STATE_UUID');
|
||||
},
|
||||
cleanEndpointData() {
|
||||
localStorageService.remove('ENDPOINT_ID', 'ENDPOINT_PUBLIC_URL', 'ENDPOINT_OFFLINE_MODE', 'ENDPOINTS_DATA', 'ENDPOINT_STATE');
|
||||
},
|
||||
storeKubernetesSummaryToggle(value) {
|
||||
localStorageService.set('kubernetes_summary_expanded', value);
|
||||
},
|
||||
|
|
|
@ -66,13 +66,14 @@ function StateManagerFactory(
|
|||
};
|
||||
|
||||
manager.clean = function () {
|
||||
state.endpoint = {};
|
||||
manager.cleanEndpoint();
|
||||
state.application = {};
|
||||
};
|
||||
|
||||
manager.cleanEndpoint = function () {
|
||||
state.endpoint = {};
|
||||
EndpointProvider.clean();
|
||||
LocalStorage.cleanEndpointState();
|
||||
};
|
||||
|
||||
manager.updateLogo = function (logoURL) {
|
||||
|
@ -208,7 +209,7 @@ function StateManagerFactory(
|
|||
state.endpoint.apiVersion = endpointAPIVersion;
|
||||
|
||||
if (endpointMode.agentProxy && endpoint.Status === 1) {
|
||||
return AgentPingService.ping().then(function onPingSuccess(data) {
|
||||
return AgentPingService.ping(endpoint.Id).then(function onPingSuccess(data) {
|
||||
state.endpoint.agentApiVersion = data.version;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
import { Environment } from '@/react/portainer/environments/types';
|
||||
|
||||
export interface EndpointProvider {
|
||||
setEndpointID(id: Environment['Id']): void;
|
||||
setEndpointPublicURL(url?: string): void;
|
||||
setOfflineModeFromStatus(status: Environment['Status']): void;
|
||||
setCurrentEndpoint(endpoint: Environment | undefined): void;
|
||||
}
|
||||
|
||||
export interface StateManager {
|
||||
updateEndpointState(endpoint: Environment): Promise<void>;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ angular.module('portainer.app').controller('StackController', [
|
|||
'TaskHelper',
|
||||
'Notifications',
|
||||
'FormHelper',
|
||||
'EndpointProvider',
|
||||
'GroupService',
|
||||
'ModalService',
|
||||
'StackHelper',
|
||||
|
@ -46,7 +45,6 @@ angular.module('portainer.app').controller('StackController', [
|
|||
TaskHelper,
|
||||
Notifications,
|
||||
FormHelper,
|
||||
EndpointProvider,
|
||||
GroupService,
|
||||
ModalService,
|
||||
StackHelper,
|
||||
|
@ -112,16 +110,12 @@ angular.module('portainer.app').controller('StackController', [
|
|||
$scope.duplicateStack = function duplicateStack(name, targetEndpointId) {
|
||||
var stack = $scope.stack;
|
||||
var env = FormHelper.removeInvalidEnvVars($scope.formValues.Env);
|
||||
// sets the targetEndpointID as global for interceptors
|
||||
EndpointProvider.setEndpointID(targetEndpointId);
|
||||
|
||||
return StackService.duplicateStack(name, $scope.stackFileContent, env, targetEndpointId, stack.Type).then(onDuplicationSuccess).catch(notifyOnError);
|
||||
|
||||
function onDuplicationSuccess() {
|
||||
Notifications.success('Success', 'Stack successfully duplicated');
|
||||
$state.go('docker.stacks', {}, { reload: true });
|
||||
// sets back the original endpointID as global for interceptors
|
||||
EndpointProvider.setEndpointID(stack.EndpointId);
|
||||
}
|
||||
|
||||
function notifyOnError(err) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue