Fix releases not reloading when selecting namespaces (#2515)

This commit is contained in:
Sebastian Malton committed 2021-04-19 11:46:07 -04:00
1 parent 92139d26ed
commit c79b6c0015
8 files changed
+128 -117

No files matched your search

@@ -1,5 +1,5 @@
import isEqual from "lodash/isEqual";
import { action, IReactionDisposer, observable, reaction, when } from "mobx";
import { action, observable, reaction, when } from "mobx";
import { autobind } from "../../utils";
import { HelmRelease, helmReleasesApi, IReleaseCreatePayload, IReleaseUpdatePayload } from "../../api/endpoints/helm-releases.api";
import { ItemStore } from "../../item.store";
@@ -10,64 +10,64 @@ import { Notifications } from "../notifications";
@autobind()
export class ReleaseStore extends ItemStore<HelmRelease> {
@observable releaseSecrets: Secret[] = [];
@observable secretWatcher: IReactionDisposer;
releaseSecrets = observable.map<string, Secret>();
constructor() {
super();
when(() => secretsStore.isLoaded, () => {
this.releaseSecrets = this.getReleaseSecrets();
this.releaseSecrets.replace(this.getReleaseSecrets());
});
}
watch() {
this.secretWatcher = reaction(() => secretsStore.items.toJS(), () => {
watchAssociatedSecrets(): (() => void) {
return reaction(() => secretsStore.items.toJS(), () => {
if (this.isLoading) return;
const secrets = this.getReleaseSecrets();
const amountChanged = secrets.length !== this.releaseSecrets.length;
const labelsChanged = this.releaseSecrets.some(item => {
const secret = secrets.find(secret => secret.getId() == item.getId());
if (!secret) return;
return !isEqual(item.getLabels(), secret.getLabels());
});
const newSecrets = this.getReleaseSecrets();
const amountChanged = newSecrets.length !== this.releaseSecrets.size;
const labelsChanged = newSecrets.some(([id, secret]) => (
!isEqual(secret.getLabels(), this.releaseSecrets.get(id)?.getLabels())
));
if (amountChanged || labelsChanged) {
this.loadFromContextNamespaces();
}
this.releaseSecrets = [...secrets];
this.releaseSecrets.replace(newSecrets);
});
}
unwatch() {
this.secretWatcher();
watchSelecteNamespaces(): (() => void) {
return reaction(() => namespaceStore.context.contextNamespaces, namespaces => {
this.loadAll(namespaces);
});
}
getReleaseSecrets() {
return secretsStore.getByLabel({ owner: "helm" });
private getReleaseSecrets() {
return secretsStore
.getByLabel({ owner: "helm" })
.map(s => [s.getId(), s] as const);
}
getReleaseSecret(release: HelmRelease) {
const labels = {
return secretsStore.getByLabel({
owner: "helm",
name: release.getName()
};
return secretsStore.getByLabel(labels)
.filter(secret => secret.getNs() == release.getNs())[0];
})
.find(secret => secret.getNs() == release.getNs());
}
@action
async loadAll(namespaces: string[]) {
this.isLoading = true;
this.isLoaded = false;
try {
const items = await this.loadItems(namespaces);
this.items.replace(this.sortItems(items));
this.isLoaded = true;
this.failedLoading = false;
} catch (error) {
this.failedLoading = true;
console.error("Loading Helm Chart releases has failed", error);
if (error.error) {
@@ -79,17 +79,18 @@ export class ReleaseStore extends ItemStore<HelmRelease> {
}
async loadFromContextNamespaces(): Promise<void> {
return this.loadAll(namespaceStore.contextNamespaces);
return this.loadAll(namespaceStore.context.contextNamespaces);
}
async loadItems(namespaces: string[]) {
const isLoadingAll = namespaceStore.allowedNamespaces.every(ns => namespaces.includes(ns));
const noAccessibleNamespaces = namespaceStore.context.cluster.accessibleNamespaces.length === 0;
const isLoadingAll = namespaceStore.context.allNamespaces?.length > 1
&& namespaceStore.context.cluster.accessibleNamespaces.length === 0
&& namespaceStore.context.allNamespaces.every(ns => namespaces.includes(ns));
if (isLoadingAll && noAccessibleNamespaces) {
if (isLoadingAll) {
return helmReleasesApi.list();
} else {
return Promise
return Promise // load resources per namespace
.all(namespaces.map(namespace => helmReleasesApi.list(namespace)))
.then(items => items.flat());
}
@@ -2,7 +2,7 @@ import "./releases.scss";
import React, { Component } from "react";
import kebabCase from "lodash/kebabCase";
import { observer } from "mobx-react";
import { disposeOnUnmount, observer } from "mobx-react";
import { RouteComponentProps } from "react-router";
import { releaseStore } from "./release.store";
import { IReleaseRouteParams, releaseURL } from "./release.route";
@@ -30,14 +30,11 @@ interface Props extends RouteComponentProps<IReleaseRouteParams> {
@observer
export class HelmReleases extends Component<Props> {
componentDidMount() {
// Watch for secrets associated with releases and react to their changes
releaseStore.watch();
}
componentWillUnmount() {
releaseStore.unwatch();
disposeOnUnmount(this, [
releaseStore.watchAssociatedSecrets(),
releaseStore.watchSelecteNamespaces(),
]);
}
get selectedRelease() {
@@ -49,21 +46,16 @@ export class HelmReleases extends Component<Props> {
}
showDetails = (item: HelmRelease) => {
if (!item) {
navigation.merge(releaseURL());
}
else {
navigation.merge(releaseURL({
params: {
name: item.getName(),
namespace: item.getNs()
}
}));
}
navigation.merge(releaseURL({
params: {
name: item.getName(),
namespace: item.getNs()
}
}));
};
hideDetails = () => {
this.showDetails(null);
navigation.merge(releaseURL());
};
renderRemoveDialogMessage(selectedItems: HelmRelease[]) {
@@ -114,30 +106,22 @@ export class HelmReleases extends Component<Props> {
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
{ title: "Updated", className: "updated", sortBy: columnId.updated, id: columnId.updated },
]}
renderTableContents={(release: HelmRelease) => {
const version = release.getVersion();
return [
release.getName(),
release.getNs(),
release.getChart(),
release.getRevision(),
<>
{version}
</>,
release.appVersion,
{ title: release.getStatus(), className: kebabCase(release.getStatus()) },
release.getUpdated(),
];
}}
renderItemMenu={(release: HelmRelease) => {
return (
<HelmReleaseMenu
release={release}
removeConfirmationMessage={this.renderRemoveDialogMessage([release])}
/>
);
}}
renderTableContents={(release: HelmRelease) => [
release.getName(),
release.getNs(),
release.getChart(),
release.getRevision(),
release.getVersion(),
release.appVersion,
{ title: release.getStatus(), className: kebabCase(release.getStatus()) },
release.getUpdated(),
]}
renderItemMenu={(release: HelmRelease) => (
<HelmReleaseMenu
release={release}
removeConfirmationMessage={this.renderRemoveDialogMessage([release])}
/>
)}
customizeRemoveDialog={(selectedItems: HelmRelease[]) => ({
message: this.renderRemoveDialogMessage(selectedItems)
})}