1
0
Fork 0
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:
Chaim Lev-Ari 2022-11-02 13:29:26 +02:00 committed by GitHub
parent 9ef2e27aae
commit 37d4a80769
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 155 additions and 353 deletions

View file

@ -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;
},
]);

View file

@ -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 });
});

View file

@ -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();

View file

@ -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;
}
);

View 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>;

View file

@ -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;

View file

@ -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);
},

View file

@ -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;
});
}

View file

@ -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>;
}

View file

@ -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) {