1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Introduce kludge to make "isEnabledForCluster" work again for kube object status texts PART 3 (#5802)

* Kludge "isEnabledForCluster" work again for kube object status texts

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>

* Kludge "isEnabledForCluster" work again for kube object menu items (#5803)

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2022-07-12 21:26:50 +03:00 committed by GitHub
parent d091f477b1
commit a1739150c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 3184 additions and 276 deletions

View File

@ -0,0 +1,165 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest";
import type { RenderResult } from "@testing-library/react";
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
import type { KubernetesCluster } from "../../../../common/catalog-entities";
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake";
import { getInjectable } from "@ogre-tools/injectable";
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
import { computed } from "mobx";
import React from "react";
import { navigateToRouteInjectionToken } from "../../../../common/front-end-routing/navigate-to-route-injection-token";
import { routeSpecificComponentInjectionToken } from "../../../../renderer/routes/route-specific-component-injection-token";
import { KubeObject } from "../../../../common/k8s-api/kube-object";
import extensionShouldBeEnabledForClusterFrameInjectable from "../../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
import { KubeObjectMenu } from "../../../../renderer/components/kube-object-menu";
import apiManagerInjectable from "../../../../common/k8s-api/api-manager/manager.injectable";
describe("disable kube object menu items when cluster is not relevant", () => {
let builder: ApplicationBuilder;
let rendered: RenderResult;
let isEnabledForClusterMock: AsyncFnMock<
(cluster: KubernetesCluster) => Promise<boolean>
>;
beforeEach(async () => {
builder = getApplicationBuilder();
builder.beforeApplicationStart(({ mainDi }) => {
mainDi.override(apiManagerInjectable, () => ({}));
});
const rendererDi = builder.dis.rendererDi;
rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
builder.setEnvironmentToClusterFrame();
const getExtensionFake = getExtensionFakeFor(builder);
isEnabledForClusterMock = asyncFn();
const testExtension = getExtensionFake({
id: "test-extension-id",
name: "test-extension",
rendererOptions: {
isEnabledForCluster: isEnabledForClusterMock,
kubeObjectMenuItems: [
{
kind: "some-kind",
apiVersions: ["some-api-version"],
components: {
MenuItem: () => (
<div data-testid="some-test-id">Some menu item</div>
),
},
},
],
},
});
rendered = await builder.render();
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
const testRoute = rendererDi.inject(testRouteInjectable);
navigateToRoute(testRoute);
builder.extensions.enable(testExtension);
});
describe("given not yet known if extension should be enabled for the cluster", () => {
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("does not show the kube object menu item", () => {
const actual = rendered.queryByTestId("some-test-id");
expect(actual).not.toBeInTheDocument();
});
});
describe("given extension shouldn't be enabled for the cluster", () => {
beforeEach(async () => {
await isEnabledForClusterMock.resolve(false);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("does not show the kube object menu item", () => {
const actual = rendered.queryByTestId("some-test-id");
expect(actual).not.toBeInTheDocument();
});
});
describe("given extension should be enabled for the cluster", () => {
beforeEach(async () => {
await isEnabledForClusterMock.resolve(true);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("shows the kube object menu item", () => {
const actual = rendered.getByTestId("some-test-id");
expect(actual).toBeInTheDocument();
});
});
});
const testRouteInjectable = getInjectable({
id: "test-route",
instantiate: () => ({
path: "/test-route",
clusterFrame: true,
isEnabled: computed(() => true),
}),
injectionToken: frontEndRouteInjectionToken,
});
const testRouteComponentInjectable = getInjectable({
id: "test-route-component",
instantiate: (di) => ({
route: di.inject(testRouteInjectable),
Component: () => (
<KubeObjectMenu
toolbar={true}
object={getKubeObjectStub("some-kind", "some-api-version")}
/>
),
}),
injectionToken: routeSpecificComponentInjectionToken,
});
const getKubeObjectStub = (kind: string, apiVersion: string) =>
KubeObject.create({
apiVersion,
kind,
metadata: {
uid: "some-uid",
name: "some-name",
resourceVersion: "some-resource-version",
namespace: "some-namespace",
selfLink: "",
},
});

View File

@ -0,0 +1,160 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest";
import type { RenderResult } from "@testing-library/react";
import type { ApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
import type { KubernetesCluster } from "../../../../common/catalog-entities";
import { getApplicationBuilder } from "../../../../renderer/components/test-utils/get-application-builder";
import { getExtensionFakeFor } from "../../../../renderer/components/test-utils/get-extension-fake";
import { getInjectable } from "@ogre-tools/injectable";
import { frontEndRouteInjectionToken } from "../../../../common/front-end-routing/front-end-route-injection-token";
import { computed } from "mobx";
import React from "react";
import { navigateToRouteInjectionToken } from "../../../../common/front-end-routing/navigate-to-route-injection-token";
import { routeSpecificComponentInjectionToken } from "../../../../renderer/routes/route-specific-component-injection-token";
import { KubeObjectStatusIcon } from "../../../../renderer/components/kube-object-status-icon/kube-object-status-icon";
import { KubeObject } from "../../../../common/k8s-api/kube-object";
import { KubeObjectStatusLevel } from "../../../../common/k8s-api/kube-object-status";
import extensionShouldBeEnabledForClusterFrameInjectable from "../../../../renderer/extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
describe("disable kube object statuses when cluster is not relevant", () => {
let builder: ApplicationBuilder;
let rendered: RenderResult;
let isEnabledForClusterMock: AsyncFnMock<
(cluster: KubernetesCluster) => Promise<boolean>
>;
beforeEach(async () => {
builder = getApplicationBuilder();
const rendererDi = builder.dis.rendererDi;
rendererDi.unoverride(extensionShouldBeEnabledForClusterFrameInjectable);
rendererDi.register(testRouteInjectable, testRouteComponentInjectable);
builder.setEnvironmentToClusterFrame();
const getExtensionFake = getExtensionFakeFor(builder);
isEnabledForClusterMock = asyncFn();
const testExtension = getExtensionFake({
id: "test-extension-id",
name: "test-extension",
rendererOptions: {
isEnabledForCluster: isEnabledForClusterMock,
kubeObjectStatusTexts: [
{
kind: "some-kind",
apiVersions: ["some-api-version"],
resolve: () => ({
level: KubeObjectStatusLevel.CRITICAL,
text: "some-kube-object-status-text",
}),
},
],
},
});
rendered = await builder.render();
const navigateToRoute = rendererDi.inject(navigateToRouteInjectionToken);
const testRoute = rendererDi.inject(testRouteInjectable);
navigateToRoute(testRoute);
builder.extensions.enable(testExtension);
});
describe("given not yet known if extension should be enabled for the cluster", () => {
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("does not show the status", () => {
const actual = rendered.baseElement.querySelectorAll(".KubeObjectStatusIcon");
expect(actual).toHaveLength(0);
});
});
describe("given extension shouldn't be enabled for the cluster", () => {
beforeEach(async () => {
await isEnabledForClusterMock.resolve(false);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("does not show the status", () => {
const actual = rendered.baseElement.querySelectorAll(".KubeObjectStatusIcon");
expect(actual).toHaveLength(0);
});
});
describe("given extension should be enabled for the cluster", () => {
beforeEach(async () => {
await isEnabledForClusterMock.resolve(true);
});
it("renders", () => {
expect(rendered.baseElement).toMatchSnapshot();
});
it("shows the status", () => {
const actual = rendered.baseElement.querySelectorAll(".KubeObjectStatusIcon");
expect(actual).toHaveLength(1);
});
});
});
const testRouteInjectable = getInjectable({
id: "test-route",
instantiate: () => ({
path: "/test-route",
clusterFrame: true,
isEnabled: computed(() => true),
}),
injectionToken: frontEndRouteInjectionToken,
});
const testRouteComponentInjectable = getInjectable({
id: "test-route-component",
instantiate: (di) => ({
route: di.inject(testRouteInjectable),
Component: () => (
<KubeObjectStatusIcon
object={getKubeObjectStub("some-kind", "some-api-version")}
/>
),
}),
injectionToken: routeSpecificComponentInjectionToken,
});
const getKubeObjectStub = (kind: string, apiVersion: string) =>
KubeObject.create({
apiVersion,
kind,
metadata: {
uid: "some-uid",
name: "some-name",
resourceVersion: "some-resource-version",
namespace: "some-namespace",
selfLink: "/foo",
},
});

View File

@ -1,31 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { conforms, includes, eq } from "lodash/fp";
import type { KubeObject } from "../../../../../common/k8s-api/kube-object";
import type { LensRendererExtension } from "../../../../../extensions/lens-renderer-extension";
import { staticKubeObjectMenuItems as staticMenuItems } from "../static-kube-object-menu-items";
interface Dependencies {
extensions: LensRendererExtension[];
kubeObject: KubeObject | null | undefined;
}
export const getKubeObjectMenuItems = ({
extensions,
kubeObject,
}: Dependencies) => {
return [
...staticMenuItems,
...extensions.flatMap((extension) => extension.kubeObjectMenuItems),
]
.filter(
conforms({
kind: eq(kubeObject?.kind),
apiVersions: includes(kubeObject?.apiVersion),
}),
)
.map((item) => item.components.MenuItem);
};

View File

@ -1,22 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import { getKubeObjectMenuItems } from "./get-kube-object-menu-items";
import type { KubeObject } from "../../../../../common/k8s-api/kube-object";
import rendererExtensionsInjectable from "../../../../../extensions/renderer-extensions.injectable";
const kubeObjectMenuItemsInjectable = getInjectable({
id: "kube-object-menu-items",
instantiate: (di, { kubeObject }: { kubeObject: KubeObject }) =>
getKubeObjectMenuItems({
extensions: di.inject(rendererExtensionsInjectable).get(),
kubeObject,
}),
lifecycle: lifecycleEnum.transient,
});
export default kubeObjectMenuItemsInjectable;

View File

@ -1,39 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { ServiceAccountMenu } from "../../+user-management/+service-accounts/service-account-menu";
import { CronJobMenu } from "../../+workloads-cronjobs/cron-job-menu";
import { DeploymentMenu } from "../../+workloads-deployments/deployment-menu";
import { ReplicaSetMenu } from "../../+workloads-replicasets/replica-set-menu";
export const staticKubeObjectMenuItems = [
{
kind: "ServiceAccount",
apiVersions: ["v1"],
components: {
MenuItem: ServiceAccountMenu,
},
},
{
kind: "CronJob",
apiVersions: ["batch/v1beta1"],
components: {
MenuItem: CronJobMenu,
},
},
{
kind: "Deployment",
apiVersions: ["apps/v1"],
components: {
MenuItem: DeploymentMenu,
},
},
{
kind: "ReplicaSet",
apiVersions: ["apps/v1"],
components: {
MenuItem: ReplicaSetMenu,
},
},
];

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { IComputedValue } from "mobx";
import type { KubeObjectMenuProps } from "./kube-object-menu";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
import type React from "react";
export type KubeObjectMenuItemComponent = React.ElementType<
KubeObjectMenuProps<KubeObject>
>;
export interface KubeObjectMenuItem {
kind: string;
apiVersions: string[];
enabled: IComputedValue<boolean>;
Component: KubeObjectMenuItemComponent;
orderNumber: number;
}
export const kubeObjectMenuItemInjectionToken = getInjectionToken<KubeObjectMenuItem>({
id: "kube-object-menu-item-injection-token",
});

View File

@ -0,0 +1,59 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { extensionRegistratorInjectionToken } from "../../../extensions/extension-loader/extension-registrator-injection-token";
import type { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable";
import extensionShouldBeEnabledForClusterFrameInjectable from "../../extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
import { kubeObjectMenuItemInjectionToken } from "./kube-object-menu-item-injection-token";
import { computed } from "mobx";
const kubeObjectMenuItemRegistratorInjectable = getInjectable({
id: "kube-object-menu-item-registrator",
instantiate: (di) => {
const getRandomId = di.inject(getRandomIdInjectable);
const getExtensionShouldBeEnabledForClusterFrame = (
extension: LensRendererExtension,
) =>
di.inject(extensionShouldBeEnabledForClusterFrameInjectable, extension);
return (ext) => {
const extension = ext as LensRendererExtension;
const extensionShouldBeEnabledForClusterFrame =
getExtensionShouldBeEnabledForClusterFrame(extension);
return extension.kubeObjectMenuItems.map((registration) => {
const id = `kube-object-menu-item-registration-from-${
extension.sanitizedExtensionId
}-${getRandomId()}`;
return getInjectable({
id,
instantiate: () => ({
kind: registration.kind,
apiVersions: registration.apiVersions,
Component: registration.components.MenuItem,
enabled: computed(() =>
extensionShouldBeEnabledForClusterFrame.value.get(),
),
orderNumber: 100,
}),
injectionToken: kubeObjectMenuItemInjectionToken,
});
});
};
},
injectionToken: extensionRegistratorInjectionToken,
});
export default kubeObjectMenuItemRegistratorInjectable;

View File

@ -0,0 +1,43 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
import { computed } from "mobx";
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
import { kubeObjectMenuItemInjectionToken } from "./kube-object-menu-item-injection-token";
import { filter, map, sortBy } from "lodash/fp";
import { pipeline } from "@ogre-tools/fp";
const kubeObjectMenuItemsInjectable = getInjectable({
id: "kube-object-menu-items",
instantiate: (di, kubeObject: KubeObject) => {
const computedInjectMany = di.inject(computedInjectManyInjectable);
const menuItems = computedInjectMany(kubeObjectMenuItemInjectionToken);
return computed(() =>
pipeline(
menuItems.get(),
filter(
(item) =>
item.kind === kubeObject?.kind &&
item.apiVersions.includes(kubeObject?.apiVersion) &&
item.enabled.get(),
),
sortBy((item) => item.orderNumber),
map((item) => item.Component),
),
);
},
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di, kubeObject: KubeObject) => kubeObject?.getId(),
}),
});
export default kubeObjectMenuItemsInjectable;

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { KubeObjectMenuItemComponent } from "../kube-object-menu-item-injection-token";
import { kubeObjectMenuItemInjectionToken } from "../kube-object-menu-item-injection-token";
import { computed } from "mobx";
import { CronJobMenu } from "../../+workloads-cronjobs/cron-job-menu";
const cronJobMenuInjectable = getInjectable({
id: "cron-job-menu-kube-object-menu",
instantiate: () => ( {
kind: "CronJob",
apiVersions: ["batch/v1beta1"],
Component: CronJobMenu as KubeObjectMenuItemComponent,
enabled: computed(() => true),
orderNumber: 20,
}),
injectionToken: kubeObjectMenuItemInjectionToken,
});
export default cronJobMenuInjectable;

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { KubeObjectMenuItemComponent } from "../kube-object-menu-item-injection-token";
import { kubeObjectMenuItemInjectionToken } from "../kube-object-menu-item-injection-token";
import { computed } from "mobx";
import { DeploymentMenu } from "../../+workloads-deployments/deployment-menu";
const deploymentMenuInjectable = getInjectable({
id: "deployment-menu-kube-object-menu",
instantiate: () => ({
kind: "Deployment",
apiVersions: ["apps/v1"],
Component: DeploymentMenu as KubeObjectMenuItemComponent,
enabled: computed(() => true),
orderNumber: 30,
}),
injectionToken: kubeObjectMenuItemInjectionToken,
});
export default deploymentMenuInjectable;

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { KubeObjectMenuItemComponent } from "../kube-object-menu-item-injection-token";
import { kubeObjectMenuItemInjectionToken } from "../kube-object-menu-item-injection-token";
import { computed } from "mobx";
import { ReplicaSetMenu } from "../../+workloads-replicasets/replica-set-menu";
const replicaSetMenuInjectable = getInjectable({
id: "replica-set-menu-kube-object-menu",
instantiate: () => ({
kind: "ReplicaSet",
apiVersions: ["apps/v1"],
Component: ReplicaSetMenu as KubeObjectMenuItemComponent,
enabled: computed(() => true),
orderNumber: 40,
}),
injectionToken: kubeObjectMenuItemInjectionToken,
});
export default replicaSetMenuInjectable;

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { KubeObjectMenuItemComponent } from "../kube-object-menu-item-injection-token";
import { kubeObjectMenuItemInjectionToken } from "../kube-object-menu-item-injection-token";
import { ServiceAccountMenu } from "../../+user-management/+service-accounts/service-account-menu";
import { computed } from "mobx";
const serviceAccountMenuInjectable = getInjectable({
id: "service-account-menu-kube-object-menu",
instantiate: () => ({
kind: "ServiceAccount",
apiVersions: ["v1"],
Component: ServiceAccountMenu as KubeObjectMenuItemComponent,
enabled: computed(() => true),
orderNumber: 10,
}),
injectionToken: kubeObjectMenuItemInjectionToken,
});
export default serviceAccountMenuInjectable;

View File

@ -8,12 +8,13 @@ import { screen, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect"; import "@testing-library/jest-dom/extend-expect";
import { KubeObject } from "../../../common/k8s-api/kube-object"; import { KubeObject } from "../../../common/k8s-api/kube-object";
import userEvent from "@testing-library/user-event"; import userEvent from "@testing-library/user-event";
import { getInjectable } from "@ogre-tools/injectable";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import { ConfirmDialog } from "../confirm-dialog"; import { ConfirmDialog } from "../confirm-dialog";
import type { AsyncFnMock } from "@async-fn/jest"; import type { AsyncFnMock } from "@async-fn/jest";
import asyncFn from "@async-fn/jest"; import asyncFn from "@async-fn/jest";
import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import { getDiForUnitTesting } from "../../getDiForUnitTesting";
import { computed } from "mobx";
import clusterInjectable from "./dependencies/cluster.injectable"; import clusterInjectable from "./dependencies/cluster.injectable";
import type { DiRender } from "../test-utils/renderFor"; import type { DiRender } from "../test-utils/renderFor";
import { renderFor } from "../test-utils/renderFor"; import { renderFor } from "../test-utils/renderFor";
@ -21,12 +22,9 @@ import type { Cluster } from "../../../common/cluster/cluster";
import type { ApiManager } from "../../../common/k8s-api/api-manager"; import type { ApiManager } from "../../../common/k8s-api/api-manager";
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
import { KubeObjectMenu } from "./index"; import { KubeObjectMenu } from "./index";
import type { KubeObjectMenuRegistration } from "./kube-object-menu-registration";
import { computed } from "mobx";
import { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable";
import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable"; import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable";
import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable"; import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable";
import { kubeObjectMenuItemInjectionToken } from "./kube-object-menu-item-injection-token";
// TODO: Make tooltips free of side effects by making it deterministic // TODO: Make tooltips free of side effects by making it deterministic
jest.mock("../tooltip/tooltip"); jest.mock("../tooltip/tooltip");
@ -35,59 +33,21 @@ jest.mock("../tooltip/withTooltip", () => ({
})); }));
// TODO: make `animated={false}` not required to make tests deterministic // TODO: make `animated={false}` not required to make tests deterministic
class SomeTestExtension extends LensRendererExtension {
constructor(
kubeObjectMenuItems: KubeObjectMenuRegistration[],
) {
super({
id: "some-id",
absolutePath: "irrelevant",
isBundled: false,
isCompatible: false,
isEnabled: false,
manifest: { name: "some-id", version: "some-version", engines: { lens: "^5.5.0" }},
manifestPath: "irrelevant",
});
this.kubeObjectMenuItems = kubeObjectMenuItems;
}
}
describe("kube-object-menu", () => { describe("kube-object-menu", () => {
let di: DiContainer; let di: DiContainer;
let render: DiRender; let render: DiRender;
beforeEach(() => { beforeEach(() => {
const MenuItemComponent = () => <li>Some menu item</li>;
const someTestExtension = new SomeTestExtension([
{
apiVersions: ["some-api-version"],
kind: "some-kind",
components: { MenuItem: MenuItemComponent },
},
{
apiVersions: ["some-unrelated-api-version"],
kind: "some-kind",
components: { MenuItem: MenuItemComponent },
},
{
apiVersions: ["some-api-version"],
kind: "some-unrelated-kind",
components: { MenuItem: MenuItemComponent },
},
]);
di = getDiForUnitTesting({ doGeneralOverrides: true }); di = getDiForUnitTesting({ doGeneralOverrides: true });
render = renderFor(di); di.register(
someMenuItemInjectable,
di.override(rendererExtensionsInjectable, () => someOtherMenuItemInjectable,
computed(() => [someTestExtension]), someAnotherMenuItemInjectable,
); );
render = renderFor(di);
di.override( di.override(
clusterInjectable, clusterInjectable,
() => () =>
@ -318,3 +278,47 @@ describe("kube-object-menu", () => {
}); });
}); });
}); });
const MenuItemComponent = () => <li>Some menu item</li>;
const someMenuItemInjectable = getInjectable({
id: "some-menu-item",
instantiate: () => ({
apiVersions: ["some-api-version"],
kind: "some-kind",
Component: MenuItemComponent,
enabled: computed(() => true),
orderNumber: 1,
}),
injectionToken: kubeObjectMenuItemInjectionToken,
});
const someOtherMenuItemInjectable = getInjectable({
id: "some-other-menu-item",
instantiate: () => ({
apiVersions: ["some-unrelated-api-version"],
kind: "some-kind",
Component: MenuItemComponent,
enabled: computed(() => true),
orderNumber: 1,
}),
injectionToken: kubeObjectMenuItemInjectionToken,
});
const someAnotherMenuItemInjectable = getInjectable({
id: "some-another-menu-item",
instantiate: () => ({
apiVersions: ["some-api-version"],
kind: "some-unrelated-kind",
Component: MenuItemComponent,
enabled: computed(() => true),
orderNumber: 1,
}),
injectionToken: kubeObjectMenuItemInjectionToken,
});

View File

@ -13,13 +13,14 @@ import type { ApiManager } from "../../../common/k8s-api/api-manager";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import clusterNameInjectable from "./dependencies/cluster-name.injectable"; import clusterNameInjectable from "./dependencies/cluster-name.injectable";
import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable"; import createEditResourceTabInjectable from "../dock/edit-resource/edit-resource-tab.injectable";
import kubeObjectMenuItemsInjectable from "./dependencies/kube-object-menu-items/kube-object-menu-items.injectable"; import kubeObjectMenuItemsInjectable from "./kube-object-menu-items.injectable";
import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable"; import apiManagerInjectable from "../../../common/k8s-api/api-manager/manager.injectable";
import type { HideDetails } from "../kube-detail-params/hide-details.injectable"; import type { HideDetails } from "../kube-detail-params/hide-details.injectable";
import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable"; import hideDetailsInjectable from "../kube-detail-params/hide-details.injectable";
import type { OnKubeObjectContextMenuOpen } from "./on-context-menu-open.injectable"; import type { OnKubeObjectContextMenuOpen } from "./on-context-menu-open.injectable";
import onKubeObjectContextMenuOpenInjectable from "./on-context-menu-open.injectable"; import onKubeObjectContextMenuOpenInjectable from "./on-context-menu-open.injectable";
import type { KubeObjectContextMenuItem } from "../../kube-object/handler"; import type { KubeObjectContextMenuItem } from "../../kube-object/handler";
import type { IComputedValue } from "mobx";
import { observable, runInAction } from "mobx"; import { observable, runInAction } from "mobx";
import type { WithConfirmation } from "../confirm-dialog/with-confirm.injectable"; import type { WithConfirmation } from "../confirm-dialog/with-confirm.injectable";
import type { Navigate } from "../../navigation/navigate.injectable"; import type { Navigate } from "../../navigation/navigate.injectable";
@ -36,7 +37,7 @@ export interface KubeObjectMenuProps<TKubeObject extends KubeObject> extends Men
interface Dependencies { interface Dependencies {
apiManager: ApiManager; apiManager: ApiManager;
kubeObjectMenuItems: React.ElementType[]; kubeObjectMenuItems: IComputedValue<React.ElementType[]>;
clusterName: string | undefined; clusterName: string | undefined;
hideDetails: HideDetails; hideDetails: HideDetails;
createEditResourceTab: (kubeObject: KubeObject) => void; createEditResourceTab: (kubeObject: KubeObject) => void;
@ -73,7 +74,7 @@ class NonInjectedKubeObjectMenu<Kube extends KubeObject> extends React.Component
private renderMenuItems() { private renderMenuItems() {
const { object, toolbar } = this.props; const { object, toolbar } = this.props;
return this.props.kubeObjectMenuItems.map((MenuItem, index) => ( return this.props.kubeObjectMenuItems.get().map((MenuItem, index) => (
<MenuItem <MenuItem
object={object} object={object}
toolbar={toolbar} toolbar={toolbar}
@ -206,9 +207,7 @@ export const KubeObjectMenu = withInjectables<Dependencies, KubeObjectMenuProps<
apiManager: di.inject(apiManagerInjectable), apiManager: di.inject(apiManagerInjectable),
createEditResourceTab: di.inject(createEditResourceTabInjectable), createEditResourceTab: di.inject(createEditResourceTabInjectable),
hideDetails: di.inject(hideDetailsInjectable), hideDetails: di.inject(hideDetailsInjectable),
kubeObjectMenuItems: di.inject(kubeObjectMenuItemsInjectable, { kubeObjectMenuItems: di.inject(kubeObjectMenuItemsInjectable, props.object),
kubeObject: props.object,
}),
onContextMenuOpen: di.inject(onKubeObjectContextMenuOpenInjectable), onContextMenuOpen: di.inject(onKubeObjectContextMenuOpenInjectable),
navigate: di.inject(navigateInjectable), navigate: di.inject(navigateInjectable),
withConfirmation: di.inject(withConfirmationInjectable), withConfirmation: di.inject(withConfirmationInjectable),

View File

@ -3,38 +3,29 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getDiForUnitTesting } from "../../getDiForUnitTesting"; import { getDiForUnitTesting } from "../../getDiForUnitTesting";
import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable";
import type { DiRender } from "../test-utils/renderFor"; import type { DiRender } from "../test-utils/renderFor";
import { renderFor } from "../test-utils/renderFor"; import { renderFor } from "../test-utils/renderFor";
import { computed } from "mobx"; import type { KubeObjectStatus } from "../../../common/k8s-api/kube-object-status";
import { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
import { KubeObjectStatusLevel } from "../../../common/k8s-api/kube-object-status"; import { KubeObjectStatusLevel } from "../../../common/k8s-api/kube-object-status";
import { KubeObject } from "../../../common/k8s-api/kube-object"; import { KubeObject } from "../../../common/k8s-api/kube-object";
import { KubeObjectStatusIcon } from "./kube-object-status-icon"; import { KubeObjectStatusIcon } from "./kube-object-status-icon";
import React from "react"; import React from "react";
import type { KubeObjectStatusRegistration } from "./kube-object-status-registration"; import { useFakeTime } from "../../../common/test-utils/use-fake-time";
import { getInjectable } from "@ogre-tools/injectable";
import type { DiContainer } from "@ogre-tools/injectable";
import { kubeObjectStatusTextInjectionToken } from "./kube-object-status-text-injection-token";
import { computed } from "mobx";
describe("kube-object-status-icon", () => { describe("kube-object-status-icon", () => {
let render: DiRender; let render: DiRender;
let kubeObjectStatusRegistrations: KubeObjectStatusRegistration[]; let di: DiContainer;
beforeEach(() => { beforeEach(() => {
// TODO: Make mocking of date in unit tests global useFakeTime("2015-10-21T07:28:00Z");
global.Date.now = () => new Date("2015-10-21T07:28:00Z").getTime();
const di = getDiForUnitTesting({ doGeneralOverrides: true }); di = getDiForUnitTesting({ doGeneralOverrides: true });
render = renderFor(di); render = renderFor(di);
kubeObjectStatusRegistrations = [];
const someTestExtension = new SomeTestExtension(
kubeObjectStatusRegistrations,
);
di.override(rendererExtensionsInjectable, () =>
computed(() => [someTestExtension]),
);
}); });
it("given no statuses, when rendered, renders as empty", () => { it("given no statuses, when rendered, renders as empty", () => {
@ -48,14 +39,14 @@ describe("kube-object-status-icon", () => {
it('given level "critical" status, when rendered, renders with status', () => { it('given level "critical" status, when rendered, renders with status', () => {
const kubeObject = getKubeObjectStub("some-kind", "some-api-version"); const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
const statusRegistration = getStatusRegistration( const statusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.CRITICAL, KubeObjectStatusLevel.CRITICAL,
"critical", "critical",
"some-kind", "some-kind",
["some-api-version"], ["some-api-version"],
); );
kubeObjectStatusRegistrations.push(statusRegistration); di.register(statusTextInjectable);
const { baseElement } = render( const { baseElement } = render(
<KubeObjectStatusIcon object={kubeObject} />, <KubeObjectStatusIcon object={kubeObject} />,
@ -67,14 +58,14 @@ describe("kube-object-status-icon", () => {
it('given level "info" status, when rendered, renders with status', () => { it('given level "info" status, when rendered, renders with status', () => {
const kubeObject = getKubeObjectStub("some-kind", "some-api-version"); const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
const statusRegistration = getStatusRegistration( const statusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.INFO, KubeObjectStatusLevel.INFO,
"info", "info",
"some-kind", "some-kind",
["some-api-version"], ["some-api-version"],
); );
kubeObjectStatusRegistrations.push(statusRegistration); di.register(statusTextInjectable);
const { baseElement } = render( const { baseElement } = render(
<KubeObjectStatusIcon object={kubeObject} />, <KubeObjectStatusIcon object={kubeObject} />,
@ -86,14 +77,14 @@ describe("kube-object-status-icon", () => {
it('given level "warning" status, when rendered, renders with status', () => { it('given level "warning" status, when rendered, renders with status', () => {
const kubeObject = getKubeObjectStub("some-kind", "some-api-version"); const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
const statusRegistration = getStatusRegistration( const statusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.WARNING, KubeObjectStatusLevel.WARNING,
"warning", "warning",
"some-kind", "some-kind",
["some-api-version"], ["some-api-version"],
); );
kubeObjectStatusRegistrations.push(statusRegistration); di.register(statusTextInjectable);
const { baseElement } = render( const { baseElement } = render(
<KubeObjectStatusIcon object={kubeObject} />, <KubeObjectStatusIcon object={kubeObject} />,
@ -105,30 +96,32 @@ describe("kube-object-status-icon", () => {
it("given status for all levels is present, when rendered, renders with statuses", () => { it("given status for all levels is present, when rendered, renders with statuses", () => {
const kubeObject = getKubeObjectStub("some-kind", "some-api-version"); const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
const critical = getStatusRegistration( const criticalStatusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.CRITICAL, KubeObjectStatusLevel.CRITICAL,
"critical", "critical",
"some-kind", "some-kind",
["some-api-version"], ["some-api-version"],
); );
const warning = getStatusRegistration( const warningStatusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.WARNING, KubeObjectStatusLevel.WARNING,
"warning", "warning",
"some-kind", "some-kind",
["some-api-version"], ["some-api-version"],
); );
const info = getStatusRegistration( const infoStatusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.INFO, KubeObjectStatusLevel.INFO,
"info", "info",
"some-kind", "some-kind",
["some-api-version"], ["some-api-version"],
); );
kubeObjectStatusRegistrations.push(critical); di.register(
kubeObjectStatusRegistrations.push(warning); criticalStatusTextInjectable,
kubeObjectStatusRegistrations.push(info); warningStatusTextInjectable,
infoStatusTextInjectable,
);
const { baseElement } = render( const { baseElement } = render(
<KubeObjectStatusIcon object={kubeObject} />, <KubeObjectStatusIcon object={kubeObject} />,
@ -140,22 +133,21 @@ describe("kube-object-status-icon", () => {
it("given info and warning statuses are present, when rendered, renders with statuses", () => { it("given info and warning statuses are present, when rendered, renders with statuses", () => {
const kubeObject = getKubeObjectStub("some-kind", "some-api-version"); const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
const warning = getStatusRegistration( const warningStatusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.WARNING, KubeObjectStatusLevel.WARNING,
"warning", "warning",
"some-kind", "some-kind",
["some-api-version"], ["some-api-version"],
); );
const info = getStatusRegistration( const infoStatusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.INFO, KubeObjectStatusLevel.INFO,
"info", "info",
"some-kind", "some-kind",
["some-api-version"], ["some-api-version"],
); );
kubeObjectStatusRegistrations.push(warning); di.register(warningStatusTextInjectable, infoStatusTextInjectable);
kubeObjectStatusRegistrations.push(info);
const { baseElement } = render( const { baseElement } = render(
<KubeObjectStatusIcon object={kubeObject} />, <KubeObjectStatusIcon object={kubeObject} />,
@ -168,14 +160,14 @@ describe("kube-object-status-icon", () => {
it("given registration for wrong api version, when rendered, renders as empty", () => { it("given registration for wrong api version, when rendered, renders as empty", () => {
const kubeObject = getKubeObjectStub("some-kind", "some-api-version"); const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
const statusRegistration = getStatusRegistration( const statusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.CRITICAL, KubeObjectStatusLevel.CRITICAL,
"irrelevant", "irrelevant",
"some-kind", "some-kind",
["some-other-api-version"], ["some-other-api-version"],
); );
kubeObjectStatusRegistrations.push(statusRegistration); di.register(statusTextInjectable);
const { baseElement } = render( const { baseElement } = render(
<KubeObjectStatusIcon object={kubeObject} />, <KubeObjectStatusIcon object={kubeObject} />,
@ -187,14 +179,14 @@ describe("kube-object-status-icon", () => {
it("given registration for wrong kind, when rendered, renders as empty", () => { it("given registration for wrong kind, when rendered, renders as empty", () => {
const kubeObject = getKubeObjectStub("some-kind", "some-api-version"); const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
const statusRegistration = getStatusRegistration( const statusTextInjectable = getStatusTextInjectable(
KubeObjectStatusLevel.CRITICAL, KubeObjectStatusLevel.CRITICAL,
"irrelevant", "irrelevant",
"some-other-kind", "some-other-kind",
["some-api-version"], ["some-api-version"],
); );
kubeObjectStatusRegistrations.push(statusRegistration); di.register(statusTextInjectable);
const { baseElement } = render( const { baseElement } = render(
<KubeObjectStatusIcon object={kubeObject} />, <KubeObjectStatusIcon object={kubeObject} />,
@ -206,21 +198,25 @@ describe("kube-object-status-icon", () => {
it("given registration without status for exact kube object, when rendered, renders as empty", () => { it("given registration without status for exact kube object, when rendered, renders as empty", () => {
const kubeObject = getKubeObjectStub("some-kind", "some-api-version"); const kubeObject = getKubeObjectStub("some-kind", "some-api-version");
const statusRegistration = { const statusTextInjectable = getInjectable({
apiVersions: ["some-api-version"], id: "some-id",
kind: "some-kind", instantiate: () => ({
resolve: (): void => {}, apiVersions: ["some-api-version"],
}; kind: "some-kind",
resolve: () => { return undefined as unknown as KubeObjectStatus; },
enabled: computed(() => true),
}),
// @ts-ignore injectionToken: kubeObjectStatusTextInjectionToken,
kubeObjectStatusRegistrations.push(statusRegistration); });
di.register(statusTextInjectable);
const { baseElement } = render( const { baseElement } = render(
<KubeObjectStatusIcon object={kubeObject} />, <KubeObjectStatusIcon object={kubeObject} />,
); );
expect(baseElement).toMatchSnapshot(); expect(baseElement).toMatchSnapshot();
}); });
}); });
@ -236,28 +232,20 @@ const getKubeObjectStub = (kind: string, apiVersion: string) => KubeObject.creat
}, },
}); });
const getStatusRegistration = (level: KubeObjectStatusLevel, title: string, kind: string, apiVersions: string[]) => ({ const getStatusTextInjectable = (level: KubeObjectStatusLevel, title: string, kind: string, apiVersions: string[]) => getInjectable({
apiVersions, id: title,
kind, instantiate: () => ({
resolve: (kubeObject: KubeObject) => ({ apiVersions,
level, kind,
text: `Some ${title} status for ${kubeObject.getName()}`,
timestamp: "2015-10-19T07:28:00Z", resolve: (kubeObject: KubeObject) => ({
level,
text: `Some ${title} status for ${kubeObject.getName()}`,
timestamp: "2015-10-19T07:28:00Z",
}),
enabled: computed(() => true),
}), }),
injectionToken: kubeObjectStatusTextInjectionToken,
}); });
class SomeTestExtension extends LensRendererExtension {
constructor(kubeObjectStatusTexts: KubeObjectStatusRegistration[]) {
super({
id: "some-id",
absolutePath: "irrelevant",
isBundled: false,
isCompatible: false,
isEnabled: false,
manifest: { name: "some-id", version: "some-version", engines: { lens: "^5.5.0" }},
manifestPath: "irrelevant",
});
this.kubeObjectStatusTexts = kubeObjectStatusTexts;
}
}

View File

@ -9,10 +9,12 @@ import React from "react";
import { Icon } from "../icon"; import { Icon } from "../icon";
import { cssNames, formatDuration, getOrInsert } from "../../utils"; import { cssNames, formatDuration, getOrInsert } from "../../utils";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import statusesForKubeObjectInjectable from "./statuses-for-kube-object.injectable"; import kubeObjectStatusTextsForObjectInjectable from "./kube-object-status-texts-for-object.injectable";
import type { KubeObject } from "../../../common/k8s-api/kube-object"; import type { KubeObject } from "../../../common/k8s-api/kube-object";
import type { KubeObjectStatus } from "../../../common/k8s-api/kube-object-status"; import type { KubeObjectStatus } from "../../../common/k8s-api/kube-object-status";
import { KubeObjectStatusLevel } from "../../../common/k8s-api/kube-object-status"; import { KubeObjectStatusLevel } from "../../../common/k8s-api/kube-object-status";
import type { IComputedValue } from "mobx";
import { observer } from "mobx-react";
function statusClassName(level: KubeObjectStatusLevel): string { function statusClassName(level: KubeObjectStatusLevel): string {
switch (level) { switch (level) {
@ -76,9 +78,10 @@ export interface KubeObjectStatusIconProps {
} }
interface Dependencies { interface Dependencies {
statuses: KubeObjectStatus[]; statuses: IComputedValue<KubeObjectStatus[]>;
} }
@observer
class NonInjectedKubeObjectStatusIcon extends React.Component<KubeObjectStatusIconProps & Dependencies> { class NonInjectedKubeObjectStatusIcon extends React.Component<KubeObjectStatusIconProps & Dependencies> {
renderStatuses(statuses: KubeObjectStatus[], level: number) { renderStatuses(statuses: KubeObjectStatus[], level: number) {
const filteredStatuses = statuses.filter((item) => item.level == level); const filteredStatuses = statuses.filter((item) => item.level == level);
@ -104,7 +107,7 @@ class NonInjectedKubeObjectStatusIcon extends React.Component<KubeObjectStatusIc
} }
render() { render() {
const statuses = this.props.statuses; const statuses = this.props.statuses.get();
if (statuses.length === 0) { if (statuses.length === 0) {
return null; return null;
@ -135,7 +138,7 @@ export const KubeObjectStatusIcon = withInjectables<Dependencies, KubeObjectStat
{ {
getProps: (di, props) => ({ getProps: (di, props) => ({
statuses: di.inject(statusesForKubeObjectInjectable, props.object), statuses: di.inject(kubeObjectStatusTextsForObjectInjectable, props.object),
...props, ...props,
}), }),
}, },

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
import type { KubeObjectStatus } from "../../../common/k8s-api/kube-object-status";
import type { IComputedValue } from "mobx";
export interface KubeObjectStatusText {
kind: string;
apiVersions: string[];
resolve: (object: KubeObject) => KubeObjectStatus;
enabled: IComputedValue<boolean>;
}
export const kubeObjectStatusTextInjectionToken =
getInjectionToken<KubeObjectStatusText>({
id: "kube-object-status-text-injection-token",
});

View File

@ -0,0 +1,55 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { extensionRegistratorInjectionToken } from "../../../extensions/extension-loader/extension-registrator-injection-token";
import type { LensRendererExtension } from "../../../extensions/lens-renderer-extension";
import getRandomIdInjectable from "../../../common/utils/get-random-id.injectable";
import { kubeObjectStatusTextInjectionToken } from "./kube-object-status-text-injection-token";
import extensionShouldBeEnabledForClusterFrameInjectable from "../../extension-loader/extension-should-be-enabled-for-cluster-frame.injectable";
import { computed } from "mobx";
const kubeObjectStatusTextRegistratorInjectable = getInjectable({
id: "kube-object-status-text-registrator",
instantiate: (di) => {
const getRandomId = di.inject(getRandomIdInjectable);
const getExtensionShouldBeEnabledForClusterFrame = (
extension: LensRendererExtension,
) =>
di.inject(extensionShouldBeEnabledForClusterFrameInjectable, extension);
return (ext) => {
const extension = ext as LensRendererExtension;
const extensionShouldBeEnabledForClusterFrame =
getExtensionShouldBeEnabledForClusterFrame(extension);
return extension.kubeObjectStatusTexts.map((registration) => {
const id = `kube-object-status-text-registration-from-${
extension.sanitizedExtensionId
}-${getRandomId()}`;
return getInjectable({
id,
instantiate: () => ({
...registration,
enabled: computed(() =>
extensionShouldBeEnabledForClusterFrame.value.get(),
),
}),
injectionToken: kubeObjectStatusTextInjectionToken,
});
});
};
},
injectionToken: extensionRegistratorInjectionToken,
});
export default kubeObjectStatusTextRegistratorInjectable;

View File

@ -0,0 +1,42 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import kubeObjectStatusTextsInjectable from "./kube-object-status-texts.injectable";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
import { conforms, eq, includes } from "lodash/fp";
import type { KubeObjectStatusRegistration } from "./kube-object-status-registration";
import { computed } from "mobx";
const kubeObjectStatusTextsForObjectInjectable = getInjectable({
id: "kube-object-status-texts-for-object",
instantiate: (di, kubeObject: KubeObject) => {
const allStatusTexts = di.inject(kubeObjectStatusTextsInjectable);
return computed(() =>
allStatusTexts
.get()
.filter(toKubeObjectRelated(kubeObject))
.map(toStatus(kubeObject))
.filter(Boolean),
);
},
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di, kubeObject: KubeObject) => kubeObject.getId(),
}),
});
const toKubeObjectRelated = (kubeObject: KubeObject) =>
conforms({
kind: eq(kubeObject.kind),
apiVersions: includes(kubeObject.apiVersion),
});
const toStatus =
(kubeObject: KubeObject) => (item: KubeObjectStatusRegistration) =>
item.resolve(kubeObject);
export default kubeObjectStatusTextsForObjectInjectable;

View File

@ -0,0 +1,23 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computedInjectManyInjectable } from "@ogre-tools/injectable-extension-for-mobx";
import { computed } from "mobx";
import { kubeObjectStatusTextInjectionToken } from "./kube-object-status-text-injection-token";
const kubeObjectStatusTextsInjectable = getInjectable({
id: "kube-object-status-texts",
instantiate: (di) => {
const computedInjectMany = di.inject(computedInjectManyInjectable);
const statusTexts = computedInjectMany(kubeObjectStatusTextInjectionToken);
return computed(() =>
statusTexts.get().filter((statusText) => statusText.enabled.get()),
);
},
});
export default kubeObjectStatusTextsInjectable;

View File

@ -1,21 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import rendererExtensionsInjectable from "../../../extensions/renderer-extensions.injectable";
const statusRegistrationsInjectable = getInjectable({
id: "status-registrations",
instantiate: (di) => {
const extensions = di.inject(rendererExtensionsInjectable);
return computed(() =>
extensions.get().flatMap((extension) => extension.kubeObjectStatusTexts),
);
},
});
export default statusRegistrationsInjectable;

View File

@ -1,35 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import statusRegistrationsInjectable from "./status-registrations.injectable";
import type { KubeObject } from "../../../common/k8s-api/kube-object";
import { conforms, eq, includes } from "lodash/fp";
import type { KubeObjectStatusRegistration } from "./kube-object-status-registration";
const statusesForKubeObjectInjectable = getInjectable({
id: "statuses-for-kube-object",
instantiate: (di, kubeObject: KubeObject) =>
di
.inject(statusRegistrationsInjectable)
.get()
.filter(toKubeObjectRelated(kubeObject))
.map(toStatus(kubeObject))
.filter(Boolean),
lifecycle: lifecycleEnum.transient,
});
const toKubeObjectRelated = (kubeObject: KubeObject) =>
conforms({
kind: eq(kubeObject.kind),
apiVersions: includes(kubeObject.apiVersion),
});
const toStatus =
(kubeObject: KubeObject) => (item: KubeObjectStatusRegistration) =>
item.resolve(kubeObject);
export default statusesForKubeObjectInjectable;