mirror of https://github.com/portainer/portainer
fix(ui): namespace caching issue EE-5273 (#8709)
* fix namespace caching issue * fix(apps): add loading state [EE-5273] * rm endpoint provider * fix(namespace): remove caching [EE-5273] * variable typo --------- Co-authored-by: testa113 <testa113>pull/8729/head
parent
d64e7eacfc
commit
fc1aec3bb8
|
@ -244,6 +244,7 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
ng-show="!$ctrl.isAppsLoading"
|
||||
ng-click="$ctrl.expandItem(item, !$ctrl.isItemExpanded(item))"
|
||||
dir-paginate-start="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.applyFilters | filter:$ctrl.state.textFilter | filter:$ctrl.isDisplayed | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit: $ctrl.tableKey))"
|
||||
ng-class="{ active: item.Checked, interactive: $ctrl.isExpandable(item), 'secondary-body': !$ctrl.isPrimary }"
|
||||
|
@ -335,16 +336,16 @@
|
|||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="!$ctrl.dataset">
|
||||
<tr ng-if="$ctrl.isAppsLoading">
|
||||
<td colspan="8" class="text-muted text-center">Loading...</td>
|
||||
</tr>
|
||||
<tr ng-if="$ctrl.state.filteredDataSet.length === 0">
|
||||
<tr ng-if="$ctrl.state.filteredDataSet.length === 0 && !$ctrl.isAppsLoading">
|
||||
<td colspan="8" class="text-muted text-center">No application available.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div ng-if="$ctrl.isPrimary" class="footer pl-5" ng-if="$ctrl.dataset">
|
||||
<div class="footer pl-5" ng-if="$ctrl.isPrimary && $ctrl.dataset">
|
||||
<div class="infoBar !ml-0" ng-if="$ctrl.state.selectedItemCount !== 0"> {{ $ctrl.state.selectedItemCount }} item(s) selected </div>
|
||||
<div class="paginationControls">
|
||||
<form class="form-inline">
|
||||
|
|
|
@ -18,6 +18,7 @@ angular.module('portainer.kubernetes').component('kubernetesApplicationsDatatabl
|
|||
namespaces: '<',
|
||||
namespace: '<',
|
||||
onChangeNamespaceDropdown: '<',
|
||||
isAppsLoading: '<',
|
||||
isSystemResources: '<',
|
||||
setSystemResources: '<',
|
||||
},
|
||||
|
|
|
@ -168,6 +168,7 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
ng-show="!$ctrl.isAppsLoading"
|
||||
dir-paginate-start="item in ($ctrl.state.filteredDataSet = ($ctrl.dataset | filter:$ctrl.state.textFilter | filter: $ctrl.isDisplayed | orderBy:$ctrl.state.orderBy:$ctrl.state.reverseOrder | itemsPerPage: $ctrl.state.paginatedItemLimit: $ctrl.tableKey))"
|
||||
ng-class="{ active: item.Checked, 'datatable-highlighted': item.Highlighted }"
|
||||
ng-click="$ctrl.expandItem(item, !item.Expanded)"
|
||||
|
@ -220,10 +221,10 @@
|
|||
>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="!$ctrl.dataset">
|
||||
<tr ng-if="$ctrl.isAppsLoading">
|
||||
<td colspan="5" class="text-muted text-center">Loading...</td>
|
||||
</tr>
|
||||
<tr ng-if="$ctrl.state.filteredDataSet.length === 0">
|
||||
<tr ng-if="$ctrl.state.filteredDataSet.length === 0 && !$ctrl.isAppsLoading">
|
||||
<td colspan="5" class="text-muted text-center">No stack available.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -13,6 +13,7 @@ angular.module('portainer.kubernetes').component('kubernetesApplicationsStacksDa
|
|||
namespaces: '<',
|
||||
namespace: '<',
|
||||
onChangeNamespaceDropdown: '<',
|
||||
isAppsLoading: '<',
|
||||
isSystemResources: '<',
|
||||
setSystemResources: '<',
|
||||
},
|
||||
|
|
|
@ -18,7 +18,6 @@ class KubernetesNamespaceService {
|
|||
this.deleteAsync = this.deleteAsync.bind(this);
|
||||
this.getJSONAsync = this.getJSONAsync.bind(this);
|
||||
this.updateFinalizeAsync = this.updateFinalizeAsync.bind(this);
|
||||
this.refreshCacheAsync = this.refreshCacheAsync.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,20 +80,13 @@ class KubernetesNamespaceService {
|
|||
}
|
||||
}
|
||||
|
||||
async get(name, refreshCache = false) {
|
||||
async get(name) {
|
||||
if (name) {
|
||||
return this.$async(this.getAsync, name);
|
||||
}
|
||||
const cachedAllowedNamespaces = this.LocalStorage.getAllowedNamespaces();
|
||||
if (!cachedAllowedNamespaces || refreshCache) {
|
||||
const allowedNamespaces = await this.getAllAsync();
|
||||
this.LocalStorage.storeAllowedNamespaces(allowedNamespaces);
|
||||
updateNamespaces(allowedNamespaces);
|
||||
return allowedNamespaces;
|
||||
} else {
|
||||
updateNamespaces(cachedAllowedNamespaces);
|
||||
return cachedAllowedNamespaces;
|
||||
}
|
||||
const allowedNamespaces = await this.getAllAsync();
|
||||
updateNamespaces(allowedNamespaces);
|
||||
return allowedNamespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,7 +97,6 @@ class KubernetesNamespaceService {
|
|||
const payload = KubernetesNamespaceConverter.createPayload(namespace);
|
||||
const params = {};
|
||||
const data = await this.KubernetesNamespaces().create(params, payload).$promise;
|
||||
await this.refreshCacheAsync();
|
||||
return data;
|
||||
} catch (err) {
|
||||
throw new PortainerError('Unable to create namespace', err);
|
||||
|
@ -116,14 +107,6 @@ class KubernetesNamespaceService {
|
|||
return this.$async(this.createAsync, namespace);
|
||||
}
|
||||
|
||||
async refreshCacheAsync() {
|
||||
this.LocalStorage.deleteAllowedNamespaces();
|
||||
const allowedNamespaces = await this.getAllAsync();
|
||||
this.LocalStorage.storeAllowedNamespaces(allowedNamespaces);
|
||||
updateNamespaces(allowedNamespaces);
|
||||
return allowedNamespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE
|
||||
*/
|
||||
|
|
|
@ -36,8 +36,8 @@ export function KubernetesResourcePoolService(
|
|||
}
|
||||
|
||||
// getting the quota for all namespaces is costly by default, so disable getting it by default
|
||||
async function getAll({ getQuota = false, refreshCache = false }) {
|
||||
const namespaces = await KubernetesNamespaceService.get('', refreshCache);
|
||||
async function getAll({ getQuota = false }) {
|
||||
const namespaces = await KubernetesNamespaceService.get();
|
||||
const pools = await Promise.all(
|
||||
_.map(namespaces, async (namespace) => {
|
||||
const name = namespace.Name;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
namespaces="ctrl.state.namespaces"
|
||||
namespace="ctrl.state.namespaceName"
|
||||
on-change-namespace-dropdown="(ctrl.onChangeNamespaceDropdown)"
|
||||
is-apps-loading="ctrl.state.isAppsLoading"
|
||||
is-system-resources="ctrl.state.isSystemResources"
|
||||
set-system-resources="(ctrl.setSystemResources)"
|
||||
>
|
||||
|
@ -38,6 +39,7 @@
|
|||
namespaces="ctrl.state.namespaces"
|
||||
namespace="ctrl.state.namespaceName"
|
||||
on-change-namespace-dropdown="(ctrl.onChangeNamespaceDropdown)"
|
||||
is-apps-loading="ctrl.state.isAppsLoading"
|
||||
is-system-resources="ctrl.state.isSystemResources"
|
||||
set-system-resources="(ctrl.setSystemResources)"
|
||||
>
|
||||
|
|
|
@ -143,15 +143,14 @@ class KubernetesApplicationsController {
|
|||
});
|
||||
}
|
||||
|
||||
onChangeNamespaceDropdown(namespaceName) {
|
||||
this.state.namespaceName = namespaceName;
|
||||
// save the selected namespaceName in local storage with the key 'kubernetes_namespace_filter_${environmentId}_${userID}'
|
||||
this.LocalStorage.storeNamespaceFilter(this.endpoint.Id, this.user.ID, namespaceName);
|
||||
this.getApplicationsAsync();
|
||||
onChangeNamespaceDropdown(namespace) {
|
||||
this.state.namespaceName = namespace;
|
||||
return this.$async(this.getApplicationsAsync);
|
||||
}
|
||||
|
||||
async getApplicationsAsync() {
|
||||
try {
|
||||
this.state.isAppsLoading = true;
|
||||
const [applications, configurations] = await Promise.all([
|
||||
this.KubernetesApplicationService.get(this.state.namespaceName),
|
||||
this.KubernetesConfigurationService.get(this.state.namespaceName),
|
||||
|
@ -166,6 +165,8 @@ class KubernetesApplicationsController {
|
|||
this.$scope.$apply();
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to retrieve applications');
|
||||
} finally {
|
||||
this.state.isAppsLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -290,7 +290,6 @@
|
|||
<!-- table -->
|
||||
<kubernetes-application-services-table
|
||||
services="ctrl.application.Services"
|
||||
namespaces="ctrl.allNamespaces"
|
||||
application="ctrl.application"
|
||||
public-url="ctrl.state.publicUrl"
|
||||
></kubernetes-application-services-table>
|
||||
|
|
|
@ -221,7 +221,6 @@ class KubernetesResourcePoolController {
|
|||
return;
|
||||
}
|
||||
await this.KubernetesResourcePoolService.toggleSystem(this.endpoint.Id, namespaceName, !this.isSystem);
|
||||
await this.KubernetesNamespaceService.refreshCacheAsync();
|
||||
|
||||
this.Notifications.success('Namespace successfully updated', namespaceName);
|
||||
this.$state.reload(this.$state.current);
|
||||
|
|
|
@ -21,7 +21,6 @@ class KubernetesResourcePoolsController {
|
|||
}
|
||||
|
||||
async onReload() {
|
||||
await this.KubernetesNamespaceService.refreshCacheAsync();
|
||||
this.$state.reload(this.$state.current);
|
||||
}
|
||||
|
||||
|
@ -50,7 +49,6 @@ class KubernetesResourcePoolsController {
|
|||
} finally {
|
||||
--actionCount;
|
||||
if (actionCount === 0) {
|
||||
await this.KubernetesNamespaceService.refreshCacheAsync();
|
||||
this.$state.reload(this.$state.current);
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +75,7 @@ class KubernetesResourcePoolsController {
|
|||
|
||||
async getResourcePoolsAsync() {
|
||||
try {
|
||||
this.resourcePools = await this.KubernetesResourcePoolService.get('', { getQuota: true, refreshCache: true });
|
||||
this.resourcePools = await this.KubernetesResourcePoolService.get('', { getQuota: true });
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to retreive namespaces');
|
||||
}
|
||||
|
|
|
@ -127,15 +127,6 @@ angular.module('portainer.app').factory('LocalStorage', [
|
|||
getKubernetesSummaryToggle() {
|
||||
return localStorageService.get('kubernetes_summary_expanded');
|
||||
},
|
||||
storeAllowedNamespaces: function (namespaces) {
|
||||
localStorageService.set('ALLOWED_NAMESPACES', namespaces);
|
||||
},
|
||||
getAllowedNamespaces: function () {
|
||||
return localStorageService.get('ALLOWED_NAMESPACES');
|
||||
},
|
||||
deleteAllowedNamespaces: function () {
|
||||
localStorageService.remove('ALLOWED_NAMESPACES');
|
||||
},
|
||||
};
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -16,7 +16,7 @@ export function useNamespaces(environmentId: EnvironmentId) {
|
|||
async () => {
|
||||
const namespaces = await getNamespaces(environmentId);
|
||||
const namespaceNames = Object.keys(namespaces);
|
||||
// use seflsubjectaccess reviews to avoid forbidden requests
|
||||
// use selfsubjectaccess reviews to avoid forbidden requests
|
||||
const allNamespaceAccessReviews = await Promise.all(
|
||||
namespaceNames.map((namespaceName) =>
|
||||
getSelfSubjectAccessReview(environmentId, namespaceName)
|
||||
|
|
Loading…
Reference in New Issue