mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
chore: Fix overriding errors by improving abstraction usage
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
a86361e09e
commit
1bc837608c
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* 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 { ConfigMapStore } from "./store";
|
||||||
|
import configMapStoreInjectable from "./store.injectable";
|
||||||
|
|
||||||
|
export type RequestConfigMap = ConfigMapStore["load"];
|
||||||
|
|
||||||
|
const requestConfigMapInjectable = getInjectable({
|
||||||
|
id: "request-config-map",
|
||||||
|
instantiate: (di): RequestConfigMap => {
|
||||||
|
const configMapStore = di.inject(configMapStoreInjectable);
|
||||||
|
|
||||||
|
return (ref) => configMapStore.load(ref);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default requestConfigMapInjectable;
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* 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 { SecretStore } from "./store";
|
||||||
|
import secretStoreInjectable from "./store.injectable";
|
||||||
|
|
||||||
|
export type RequestSecret = SecretStore["load"];
|
||||||
|
|
||||||
|
const requestSecretInjectable = getInjectable({
|
||||||
|
id: "request-secret",
|
||||||
|
instantiate: (di): RequestSecret => {
|
||||||
|
const secretStore = di.inject(secretStoreInjectable);
|
||||||
|
|
||||||
|
return (ref) => secretStore.load(ref);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default requestSecretInjectable;
|
||||||
@ -22,9 +22,12 @@ import type { GetDetailsUrl } from "../../kube-detail-params/get-details-url.inj
|
|||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import getDetailsUrlInjectable from "../../kube-detail-params/get-details-url.injectable";
|
import getDetailsUrlInjectable from "../../kube-detail-params/get-details-url.injectable";
|
||||||
import secretStoreInjectable from "../../config-secrets/store.injectable";
|
import secretStoreInjectable from "../../config-secrets/store.injectable";
|
||||||
|
import type { RequestSecret } from "../../config-secrets/request-secret.injectable";
|
||||||
|
import requestSecretInjectable from "../../config-secrets/request-secret.injectable";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
secretStore: SecretStore;
|
secretStore: SecretStore;
|
||||||
|
requestSecret: RequestSecret;
|
||||||
getDetailsUrl: GetDetailsUrl;
|
getDetailsUrl: GetDetailsUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,7 +38,7 @@ class NonInjectedServiceAccountsDetails extends React.Component<KubeObjectDetail
|
|||||||
|
|
||||||
private defensiveLoadSecretIn = (namespace: string) => (
|
private defensiveLoadSecretIn = (namespace: string) => (
|
||||||
({ name }: { name: string }) => (
|
({ name }: { name: string }) => (
|
||||||
this.props.secretStore.load({ name, namespace })
|
this.props.requestSecret({ name, namespace })
|
||||||
.catch(() => name)
|
.catch(() => name)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -164,5 +167,6 @@ export const ServiceAccountsDetails = withInjectables<Dependencies, KubeObjectDe
|
|||||||
...props,
|
...props,
|
||||||
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
getDetailsUrl: di.inject(getDetailsUrlInjectable),
|
||||||
secretStore: di.inject(secretStoreInjectable),
|
secretStore: di.inject(secretStoreInjectable),
|
||||||
|
requestSecret: di.inject(requestSecretInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,15 +5,15 @@
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import type { ConfigMapStore } from "../../config-maps/store";
|
import type { ConfigMapStore } from "../../config-maps/store";
|
||||||
import configMapStoreInjectable from "../../config-maps/store.injectable";
|
|
||||||
import type { SecretStore } from "../../config-secrets/store";
|
import type { SecretStore } from "../../config-secrets/store";
|
||||||
import secretStoreInjectable from "../../config-secrets/store.injectable";
|
|
||||||
import type { Container } from "@k8slens/kube-object";
|
import type { Container } from "@k8slens/kube-object";
|
||||||
import { Secret, ConfigMap, Pod, SecretType } from "@k8slens/kube-object";
|
import { Secret, ConfigMap, Pod, SecretType } from "@k8slens/kube-object";
|
||||||
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||||
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 { ContainerEnvironment } from "../pod-container-env";
|
import { ContainerEnvironment } from "../pod-container-env";
|
||||||
|
import requestSecretInjectable from "../../config-secrets/request-secret.injectable";
|
||||||
|
import requestConfigMapInjectable from "../../config-maps/request-config-map.injectable";
|
||||||
|
|
||||||
describe("<ContainerEnv />", () => {
|
describe("<ContainerEnv />", () => {
|
||||||
let render: DiRender;
|
let render: DiRender;
|
||||||
@ -36,8 +36,8 @@ describe("<ContainerEnv />", () => {
|
|||||||
getByName: jest.fn(),
|
getByName: jest.fn(),
|
||||||
});
|
});
|
||||||
|
|
||||||
di.override(secretStoreInjectable, () => secretStore as jest.Mocked<SecretStore>);
|
di.override(requestSecretInjectable, () => () => Promise.resolve({} as Secret));
|
||||||
di.override(configMapStoreInjectable, () => configMapStore as jest.Mocked<ConfigMapStore>);
|
di.override(requestConfigMapInjectable, () => () => Promise.resolve({} as ConfigMap));
|
||||||
|
|
||||||
render = renderFor(di);
|
render = renderFor(di);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,19 +5,20 @@
|
|||||||
|
|
||||||
import "./pod-container-env.scss";
|
import "./pod-container-env.scss";
|
||||||
|
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import type { Container } from "@k8slens/kube-object";
|
import type { ConfigMap, Container, Secret } from "@k8slens/kube-object";
|
||||||
import { DrawerItem } from "../drawer";
|
import { DrawerItem } from "../drawer";
|
||||||
import { autorun } from "mobx";
|
import { autorun, observable } from "mobx";
|
||||||
import { object } from "@k8slens/utilities";
|
import { getOrInsertWith, object } from "@k8slens/utilities";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import type { IAsyncComputed } from "@ogre-tools/injectable-react";
|
||||||
import type { ConfigMapStore } from "../config-maps/store";
|
import { asyncComputed, withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import type { SecretStore } from "../config-secrets/store";
|
|
||||||
import configMapStoreInjectable from "../config-maps/store.injectable";
|
|
||||||
import secretStoreInjectable from "../config-secrets/store.injectable";
|
|
||||||
import { SecretKey } from "./secret-key";
|
import { SecretKey } from "./secret-key";
|
||||||
|
import type { RequestSecret } from "../config-secrets/request-secret.injectable";
|
||||||
|
import requestSecretInjectable from "../config-secrets/request-secret.injectable";
|
||||||
|
import type { RequestConfigMap } from "../config-maps/request-config-map.injectable";
|
||||||
|
import requestConfigMapInjectable from "../config-maps/request-config-map.injectable";
|
||||||
|
|
||||||
export interface ContainerEnvironmentProps {
|
export interface ContainerEnvironmentProps {
|
||||||
container: Container;
|
container: Container;
|
||||||
@ -25,32 +26,49 @@ export interface ContainerEnvironmentProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
configMapStore: ConfigMapStore;
|
requestConfigMap: RequestConfigMap;
|
||||||
secretStore: SecretStore;
|
requestSecret: RequestSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NonInjectedContainerEnvironment = observer((props: Dependencies & ContainerEnvironmentProps) => {
|
const NonInjectedContainerEnvironment = observer((props: Dependencies & ContainerEnvironmentProps) => {
|
||||||
const {
|
const {
|
||||||
container: { env, envFrom = [] },
|
container: { env, envFrom = [] },
|
||||||
namespace,
|
namespace,
|
||||||
configMapStore,
|
requestConfigMap,
|
||||||
secretStore,
|
requestSecret,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const secrets = useRef(observable.map<string, IAsyncComputed<Secret>>());
|
||||||
|
const configMaps = useRef(observable.map<string, IAsyncComputed<ConfigMap>>());
|
||||||
|
|
||||||
useEffect( () => autorun(() => {
|
useEffect( () => autorun(() => {
|
||||||
for (const { valueFrom } of env ?? []) {
|
for (const { valueFrom } of env ?? []) {
|
||||||
if (valueFrom?.configMapKeyRef?.name) {
|
const { configMapKeyRef: { name } = { name: undefined }} = valueFrom ?? {};
|
||||||
void configMapStore.load({ name: valueFrom.configMapKeyRef.name, namespace });
|
|
||||||
|
if (name) {
|
||||||
|
getOrInsertWith(configMaps.current, name, () => asyncComputed({
|
||||||
|
betweenUpdates: "show-latest-value",
|
||||||
|
valueWhenPending: undefined,
|
||||||
|
getValueFromObservedPromise: () => requestConfigMap({ name, namespace }),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const { configMapRef, secretRef } of envFrom ?? []) {
|
for (const { configMapRef, secretRef } of envFrom ?? []) {
|
||||||
if (secretRef?.name) {
|
if (secretRef?.name) {
|
||||||
void secretStore.load({ name: secretRef.name, namespace });
|
getOrInsertWith(secrets.current, secretRef.name, () => asyncComputed({
|
||||||
|
betweenUpdates: "show-latest-value",
|
||||||
|
valueWhenPending: undefined,
|
||||||
|
getValueFromObservedPromise: () => requestSecret({ name: secretRef.name, namespace }),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configMapRef?.name) {
|
if (configMapRef?.name) {
|
||||||
void configMapStore.load({ name: configMapRef.name, namespace });
|
getOrInsertWith(configMaps.current, configMapRef.name, () => asyncComputed({
|
||||||
|
betweenUpdates: "show-latest-value",
|
||||||
|
valueWhenPending: undefined,
|
||||||
|
getValueFromObservedPromise: () => requestConfigMap({ name: configMapRef.name, namespace }),
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}), []);
|
}), []);
|
||||||
@ -83,7 +101,7 @@ const NonInjectedContainerEnvironment = observer((props: Dependencies & Containe
|
|||||||
);
|
);
|
||||||
} else if (configMapKeyRef?.name) {
|
} else if (configMapKeyRef?.name) {
|
||||||
const { name, key } = configMapKeyRef;
|
const { name, key } = configMapKeyRef;
|
||||||
const configMap = configMapStore.getByName(name, namespace);
|
const configMap = configMaps.current.get(name)?.value.get();
|
||||||
|
|
||||||
secretValue = configMap
|
secretValue = configMap
|
||||||
? configMap.data[key]
|
? configMap.data[key]
|
||||||
@ -117,7 +135,7 @@ const NonInjectedContainerEnvironment = observer((props: Dependencies & Containe
|
|||||||
);
|
);
|
||||||
|
|
||||||
const renderEnvFromConfigMap = (configMapName: string, prefix: string | undefined) => {
|
const renderEnvFromConfigMap = (configMapName: string, prefix: string | undefined) => {
|
||||||
const configMap = configMapStore.getByName(configMapName, namespace);
|
const configMap = configMaps.current.get(configMapName)?.value.get();
|
||||||
|
|
||||||
if (!configMap) return null;
|
if (!configMap) return null;
|
||||||
|
|
||||||
@ -135,7 +153,7 @@ const NonInjectedContainerEnvironment = observer((props: Dependencies & Containe
|
|||||||
};
|
};
|
||||||
|
|
||||||
const renderEnvFromSecret = (secretName: string, prefix: string | undefined) => {
|
const renderEnvFromSecret = (secretName: string, prefix: string | undefined) => {
|
||||||
const secret = secretStore.getByName(secretName, namespace);
|
const secret = secrets.current.get(secretName)?.value.get();
|
||||||
|
|
||||||
if (!secret) return null;
|
if (!secret) return null;
|
||||||
|
|
||||||
@ -169,7 +187,7 @@ const NonInjectedContainerEnvironment = observer((props: Dependencies & Containe
|
|||||||
export const ContainerEnvironment = withInjectables<Dependencies, ContainerEnvironmentProps>(NonInjectedContainerEnvironment, {
|
export const ContainerEnvironment = withInjectables<Dependencies, ContainerEnvironmentProps>(NonInjectedContainerEnvironment, {
|
||||||
getProps: (di, props) => ({
|
getProps: (di, props) => ({
|
||||||
...props,
|
...props,
|
||||||
configMapStore: di.inject(configMapStoreInjectable),
|
requestConfigMap: di.inject(requestConfigMapInjectable),
|
||||||
secretStore: di.inject(secretStoreInjectable),
|
requestSecret: di.inject(requestSecretInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,11 +10,11 @@ import type { RenderResult } from "@testing-library/react";
|
|||||||
import { act } from "@testing-library/react";
|
import { act } from "@testing-library/react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import type { SecretStore } from "../config-secrets/store";
|
import type { SecretStore } from "../config-secrets/store";
|
||||||
import secretStoreInjectable from "../config-secrets/store.injectable";
|
|
||||||
import { Secret, SecretType } from "@k8slens/kube-object";
|
import { Secret, SecretType } from "@k8slens/kube-object";
|
||||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||||
import { renderFor } from "../test-utils/renderFor";
|
import { renderFor } from "../test-utils/renderFor";
|
||||||
import { SecretKey } from "./secret-key";
|
import { SecretKey } from "./secret-key";
|
||||||
|
import requestSecretInjectable from "../config-secrets/request-secret.injectable";
|
||||||
|
|
||||||
describe("SecretKey technical tests", () => {
|
describe("SecretKey technical tests", () => {
|
||||||
let loadSecretMock: AsyncFnMock<SecretStore["load"]>;
|
let loadSecretMock: AsyncFnMock<SecretStore["load"]>;
|
||||||
@ -25,9 +25,7 @@ describe("SecretKey technical tests", () => {
|
|||||||
const render = renderFor(di);
|
const render = renderFor(di);
|
||||||
|
|
||||||
loadSecretMock = asyncFn();
|
loadSecretMock = asyncFn();
|
||||||
di.override(secretStoreInjectable, () => ({
|
di.override(requestSecretInjectable, () => loadSecretMock);
|
||||||
load: loadSecretMock,
|
|
||||||
} as Partial<SecretStore> as SecretStore));
|
|
||||||
|
|
||||||
result = render((
|
result = render((
|
||||||
<SecretKey
|
<SecretKey
|
||||||
|
|||||||
@ -6,10 +6,10 @@ import React, { useState } from "react";
|
|||||||
import type { EnvVarKeySelector } from "@k8slens/kube-object";
|
import type { EnvVarKeySelector } from "@k8slens/kube-object";
|
||||||
import { Icon } from "@k8slens/icon";
|
import { Icon } from "@k8slens/icon";
|
||||||
import { base64, cssNames, isObject } from "@k8slens/utilities";
|
import { base64, cssNames, isObject } from "@k8slens/utilities";
|
||||||
import type { SecretStore } from "../config-secrets/store";
|
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import secretStoreInjectable from "../config-secrets/store.injectable";
|
|
||||||
import type { SetRequired } from "type-fest";
|
import type { SetRequired } from "type-fest";
|
||||||
|
import type { RequestSecret } from "../config-secrets/request-secret.injectable";
|
||||||
|
import requestSecretInjectable from "../config-secrets/request-secret.injectable";
|
||||||
|
|
||||||
export interface SecretKeyProps {
|
export interface SecretKeyProps {
|
||||||
reference: SetRequired<EnvVarKeySelector, "name">;
|
reference: SetRequired<EnvVarKeySelector, "name">;
|
||||||
@ -17,12 +17,12 @@ export interface SecretKeyProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
secretStore: SecretStore;
|
requestSecret: RequestSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NonInjectedSecretKey = (props: SecretKeyProps & Dependencies) => {
|
const NonInjectedSecretKey = (props: SecretKeyProps & Dependencies) => {
|
||||||
const {
|
const {
|
||||||
reference: { name, key }, namespace, secretStore,
|
reference: { name, key }, namespace, requestSecret,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@ -38,7 +38,7 @@ const NonInjectedSecretKey = (props: SecretKeyProps & Dependencies) => {
|
|||||||
|
|
||||||
void (async () => {
|
void (async () => {
|
||||||
try {
|
try {
|
||||||
const secret = await secretStore.load({ name, namespace });
|
const secret = await requestSecret({ name, namespace });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setSecretData(base64.decode(secret.data[key] ?? ""));
|
setSecretData(base64.decode(secret.data[key] ?? ""));
|
||||||
@ -82,6 +82,6 @@ const NonInjectedSecretKey = (props: SecretKeyProps & Dependencies) => {
|
|||||||
export const SecretKey = withInjectables<Dependencies, SecretKeyProps>(NonInjectedSecretKey, {
|
export const SecretKey = withInjectables<Dependencies, SecretKeyProps>(NonInjectedSecretKey, {
|
||||||
getProps: (di, props) => ({
|
getProps: (di, props) => ({
|
||||||
...props,
|
...props,
|
||||||
secretStore: di.inject(secretStoreInjectable),
|
requestSecret: di.inject(requestSecretInjectable),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user