mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Introduce removeNamespaceInjectable
Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
parent
58546b0e65
commit
da3e08f303
@ -16,6 +16,7 @@ import hostedClusterInjectable from "../../cluster-frame-context/hosted-cluster.
|
|||||||
import createClusterInjectable from "../../cluster/create-cluster.injectable";
|
import createClusterInjectable from "../../cluster/create-cluster.injectable";
|
||||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||||
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-created.injectable";
|
||||||
|
import removeSubnamespaceInjectable from "./remove-subnamespace.injectable";
|
||||||
import type { NamespaceStore } from "./store";
|
import type { NamespaceStore } from "./store";
|
||||||
import namespaceStoreInjectable from "./store.injectable";
|
import namespaceStoreInjectable from "./store.injectable";
|
||||||
|
|
||||||
@ -105,9 +106,11 @@ const levelDeepSubChildA = createNamespace("level-deep-subchild-a", {
|
|||||||
"level-deep-subchild-a.tree.hnc.x-k8s.io/depth": "0",
|
"level-deep-subchild-a.tree.hnc.x-k8s.io/depth": "0",
|
||||||
});
|
});
|
||||||
|
|
||||||
const deleteMock = jest.spyOn(NamespaceApi.prototype, "delete")
|
const deleteNamespaceMock = jest.spyOn(NamespaceApi.prototype, "delete")
|
||||||
.mockImplementation();
|
.mockImplementation();
|
||||||
|
|
||||||
|
const removeSubnamespaceMock = jest.fn();
|
||||||
|
|
||||||
describe("NamespaceStore", () => {
|
describe("NamespaceStore", () => {
|
||||||
let di: DiContainer;
|
let di: DiContainer;
|
||||||
let namespaceStore: NamespaceStore;
|
let namespaceStore: NamespaceStore;
|
||||||
@ -121,6 +124,7 @@ describe("NamespaceStore", () => {
|
|||||||
di.override(directoryForUserDataInjectable, () => "/some-user-store-path");
|
di.override(directoryForUserDataInjectable, () => "/some-user-store-path");
|
||||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||||
|
di.override(removeSubnamespaceInjectable, () => removeSubnamespaceMock);
|
||||||
|
|
||||||
const createCluster = di.inject(createClusterInjectable);
|
const createCluster = di.inject(createClusterInjectable);
|
||||||
|
|
||||||
@ -223,7 +227,7 @@ describe("NamespaceStore", () => {
|
|||||||
it("removes namespace", () => {
|
it("removes namespace", () => {
|
||||||
namespaceStore.remove(fullNamespace);
|
namespaceStore.remove(fullNamespace);
|
||||||
|
|
||||||
expect(deleteMock).toBeCalledWith({ name: "full-namespace", namespace: undefined });
|
expect(deleteNamespaceMock).toBeCalledWith({ name: "full-namespace", namespace: undefined });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -231,7 +235,13 @@ describe("NamespaceStore", () => {
|
|||||||
it("does not remove namespace directly", () => {
|
it("does not remove namespace directly", () => {
|
||||||
namespaceStore.remove(service1);
|
namespaceStore.remove(service1);
|
||||||
|
|
||||||
expect(deleteMock).not.toBeCalled();
|
expect(deleteNamespaceMock).not.toBeCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls remove subnamespace function", () => {
|
||||||
|
namespaceStore.remove(service1);
|
||||||
|
|
||||||
|
expect(removeSubnamespaceMock).toBeCalledWith("service-1");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import customResourceDefinitionStoreInjectable from "../+custom-resources/definition.store.injectable";
|
||||||
|
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
|
||||||
|
import showErrorNotificationInjectable from "../notifications/show-error-notification.injectable";
|
||||||
|
import showSuccessNotificationInjectable from "../notifications/show-success-notification.injectable";
|
||||||
|
|
||||||
|
const removeSubnamespaceInjectable = getInjectable({
|
||||||
|
id: "remove-subnamespace",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const crdStore = di.inject(customResourceDefinitionStoreInjectable);
|
||||||
|
const apiManager = di.inject(apiManagerInjectable);
|
||||||
|
const showErrorNotification = di.inject(showErrorNotificationInjectable);
|
||||||
|
const showSuccessNotification = di.inject(showSuccessNotificationInjectable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removing subnamespace controlled by hierarchical namespace controller by deleting
|
||||||
|
* the SubnamespaceAnchor from the parent namespace. Anchor is CRD with the same name
|
||||||
|
* https://github.com/kubernetes-sigs/hierarchical-namespaces/blob/master/docs/user-guide/quickstart.md#subnamespaces-deep-dive
|
||||||
|
* @param subnamespaceName namespace name
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
return async (subnamespaceName: string) => {
|
||||||
|
await crdStore.loadAll();
|
||||||
|
|
||||||
|
const anchorCrd = crdStore.getByGroup("hnc.x-k8s.io", "subnamespaceanchors");
|
||||||
|
const store = apiManager.getStore(anchorCrd?.getResourceApiBase());
|
||||||
|
|
||||||
|
await store?.loadAll();
|
||||||
|
|
||||||
|
const anchor = store?.getByName(subnamespaceName);
|
||||||
|
|
||||||
|
if (!anchor) {
|
||||||
|
showErrorNotification("Error removing namespace: can not find subnamespace anchor.");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await store?.remove(anchor);
|
||||||
|
|
||||||
|
showSuccessNotification(`Subnamespace ${subnamespaceName} removed`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default removeSubnamespaceInjectable;
|
||||||
@ -12,7 +12,7 @@ import storesAndApisCanBeCreatedInjectable from "../../stores-apis-can-be-create
|
|||||||
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
import clusterFrameContextForClusterScopedResourcesInjectable from "../../cluster-frame-context/for-cluster-scoped-resources.injectable";
|
||||||
import clusterConfiguredAccessibleNamespacesInjectable from "../../cluster/accessible-namespaces.injectable";
|
import clusterConfiguredAccessibleNamespacesInjectable from "../../cluster/accessible-namespaces.injectable";
|
||||||
import loggerInjectable from "../../../common/logger.injectable";
|
import loggerInjectable from "../../../common/logger.injectable";
|
||||||
import customResourceDefinitionStoreInjectable from "../+custom-resources/definition.store.injectable";
|
import removeSubnamespaceInjectable from "./remove-subnamespace.injectable";
|
||||||
|
|
||||||
const namespaceStoreInjectable = getInjectable({
|
const namespaceStoreInjectable = getInjectable({
|
||||||
id: "namespace-store",
|
id: "namespace-store",
|
||||||
@ -28,7 +28,7 @@ const namespaceStoreInjectable = getInjectable({
|
|||||||
storage: createStorage<string[] | undefined>("selected_namespaces", undefined),
|
storage: createStorage<string[] | undefined>("selected_namespaces", undefined),
|
||||||
clusterConfiguredAccessibleNamespaces: di.inject(clusterConfiguredAccessibleNamespacesInjectable),
|
clusterConfiguredAccessibleNamespaces: di.inject(clusterConfiguredAccessibleNamespacesInjectable),
|
||||||
logger: di.inject(loggerInjectable),
|
logger: di.inject(loggerInjectable),
|
||||||
crdStore: di.inject(customResourceDefinitionStoreInjectable)
|
removeSubnamespace: di.inject(removeSubnamespaceInjectable)
|
||||||
}, api);
|
}, api);
|
||||||
},
|
},
|
||||||
injectionToken: kubeObjectStoreInjectionToken,
|
injectionToken: kubeObjectStoreInjectionToken,
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import type { KubeObjectStoreDependencies, KubeObjectStoreLoadingParams } from "
|
|||||||
import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
|
import { KubeObjectStore } from "../../../common/k8s-api/kube-object.store";
|
||||||
import type { NamespaceApi } from "../../../common/k8s-api/endpoints/namespace.api";
|
import type { NamespaceApi } from "../../../common/k8s-api/endpoints/namespace.api";
|
||||||
import { Namespace } 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 {
|
export interface NamespaceTree {
|
||||||
id: string;
|
id: string;
|
||||||
@ -22,7 +21,7 @@ export interface NamespaceTree {
|
|||||||
interface Dependencies extends KubeObjectStoreDependencies {
|
interface Dependencies extends KubeObjectStoreDependencies {
|
||||||
readonly storage: StorageLayer<string[] | undefined>;
|
readonly storage: StorageLayer<string[] | undefined>;
|
||||||
readonly clusterConfiguredAccessibleNamespaces: IComputedValue<string[]>;
|
readonly clusterConfiguredAccessibleNamespaces: IComputedValue<string[]>;
|
||||||
readonly crdStore: CustomResourceDefinitionStore;
|
readonly removeSubnamespace: (name: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NamespaceStore extends KubeObjectStore<Namespace, NamespaceApi> {
|
export class NamespaceStore extends KubeObjectStore<Namespace, NamespaceApi> {
|
||||||
@ -220,22 +219,10 @@ export class NamespaceStore extends KubeObjectStore<Namespace, NamespaceApi> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@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
|
@action
|
||||||
async remove(item: Namespace) {
|
async remove(item: Namespace) {
|
||||||
if (item.isSubnamespace()) {
|
if (item.isSubnamespace()) {
|
||||||
this.removeSubnamespace(item);
|
this.dependencies.removeSubnamespace(item.getName());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user