diff --git a/packages/core/src/renderer/components/+namespaces/namespace-store.test.ts b/packages/core/src/renderer/components/+namespaces/namespace-store.test.ts index b4e63da37a..ac70727a45 100644 --- a/packages/core/src/renderer/components/+namespaces/namespace-store.test.ts +++ b/packages/core/src/renderer/components/+namespaces/namespace-store.test.ts @@ -38,6 +38,8 @@ function createNamespace(name: string, labels?: Record, annotati }); } +const fullNamespace = createNamespace("full-namespace"); + const singleRoot = createNamespace("single-root", { "hnc.x-k8s.io/included-namespace": "true", }); @@ -133,6 +135,7 @@ describe("NamespaceStore", () => { namespaceStore = di.inject(namespaceStoreInjectable); namespaceStore.items = observable.array([ + fullNamespace, acmeGroup, orgA, teamA, @@ -146,6 +149,10 @@ describe("NamespaceStore", () => { ]); }); + afterEach(() => { + jest.clearAllMocks(); + }) + it("returns tree for single node", () => { const tree = namespaceStore.getNamespaceTree(service1); @@ -214,9 +221,17 @@ describe("NamespaceStore", () => { describe("when removing a full namespace", () => { it("removes namespace", () => { - namespaceStore.remove(acmeGroup); + namespaceStore.remove(fullNamespace); - expect(deleteMock).toBeCalledWith({ name: "acme-org", namespace: undefined }); + expect(deleteMock).toBeCalledWith({ name: "full-namespace", namespace: undefined }); + }); + }); + + describe("when removing a subnamespace", () => { + it("does not remove namespace directly", () => { + namespaceStore.remove(service1); + + expect(deleteMock).not.toBeCalled(); }); }); }); diff --git a/packages/core/src/renderer/components/+namespaces/store.injectable.ts b/packages/core/src/renderer/components/+namespaces/store.injectable.ts index 1ee9dc024f..06ae358f9b 100644 --- a/packages/core/src/renderer/components/+namespaces/store.injectable.ts +++ b/packages/core/src/renderer/components/+namespaces/store.injectable.ts @@ -12,6 +12,7 @@ import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-create import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable"; import clusterConfiguredAccessibleNamespacesInjectable from "../../cluster/accessible-namespaces.injectable"; import loggerInjectable from "../../../common/logger.injectable"; +import customResourceDefinitionStoreInjectable from "../+custom-resources/definition.store.injectable"; const namespaceStoreInjectable = getInjectable({ id: "namespace-store", @@ -27,6 +28,7 @@ const namespaceStoreInjectable = getInjectable({ storage: createStorage("selected_namespaces", undefined), clusterConfiguredAccessibleNamespaces: di.inject(clusterConfiguredAccessibleNamespacesInjectable), logger: di.inject(loggerInjectable), + crdStore: di.inject(customResourceDefinitionStoreInjectable) }, api); }, injectionToken: kubeObjectStoreInjectionToken, diff --git a/packages/core/src/renderer/components/+namespaces/store.ts b/packages/core/src/renderer/components/+namespaces/store.ts index 3e3608fb81..789b00aeb5 100644 --- a/packages/core/src/renderer/components/+namespaces/store.ts +++ b/packages/core/src/renderer/components/+namespaces/store.ts @@ -11,6 +11,7 @@ import type { KubeObjectStoreDependencies, KubeObjectStoreLoadingParams } from " import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; import type { NamespaceApi } from "../../../common/k8s-api/endpoints/namespace.api"; import { Namespace } from "../../../common/k8s-api/endpoints/namespace.api"; +import type { CustomResourceDefinitionStore } from "../+custom-resources/definition.store"; export interface NamespaceTree { id: string; @@ -21,6 +22,7 @@ export interface NamespaceTree { interface Dependencies extends KubeObjectStoreDependencies { readonly storage: StorageLayer; readonly clusterConfiguredAccessibleNamespaces: IComputedValue; + readonly crdStore: CustomResourceDefinitionStore; } export class NamespaceStore extends KubeObjectStore { @@ -218,8 +220,26 @@ export class NamespaceStore extends KubeObjectStore { }; } + @action + async removeSubnamespace(item: Namespace) { + // Remove anchor from the parent namespace + const crd = this.dependencies.crdStore.getByName(item.getName()); + + if (!crd) { + return; + } + + this.dependencies.crdStore.remove(crd); + } + @action async remove(item: Namespace) { + if (item.isSubnamespace()) { + this.removeSubnamespace(item); + + return; + } + await super.remove(item); this.clearSelected(item.getName()); }