From 8dce32153f1dc70f57cb0c2d1b80a08149f96f65 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Mon, 24 Apr 2023 09:53:44 -0400 Subject: [PATCH 01/16] ci: Fix test of 'Cron Test' workflow Signed-off-by: Sebastian Malton --- .github/workflows/cron-test.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cron-test.yaml b/.github/workflows/cron-test.yaml index 2358a34e9a..5be4bfac2d 100644 --- a/.github/workflows/cron-test.yaml +++ b/.github/workflows/cron-test.yaml @@ -51,7 +51,7 @@ jobs: command: npm ci - name: Build library parts - run: run npm build -- --ignore open-lens + run: npm run build -- --ignore open-lens - run: npm run test:unit name: Run tests From 2f21ba51d1a149251e0fa0d6fb31fdafdc889a78 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 15:48:38 -0400 Subject: [PATCH 02/16] chore: Change parseKubeApi into a no-throw version Signed-off-by: Sebastian Malton --- .../k8s-api/__tests__/kube-api-parse.test.ts | 6 +- .../common/k8s-api/api-manager/api-manager.ts | 13 ++-- .../core/src/common/k8s-api/kube-api-parse.ts | 66 +++++++++---------- packages/core/src/common/k8s-api/kube-api.ts | 42 +++++++----- .../get-kube-api-from-path.injectable.ts | 8 +-- .../src/common/k8s-api/kube-object.store.ts | 6 +- ...y-decorator-for-show-details.injectable.ts | 15 +++-- .../telemetry/show-details-calls.test.ts | 10 +-- .../call-for-resource.injectable.ts | 2 +- .../edit-resource-model.injectable.tsx | 25 ++++++- 10 files changed, 113 insertions(+), 80 deletions(-) diff --git a/packages/core/src/common/k8s-api/__tests__/kube-api-parse.test.ts b/packages/core/src/common/k8s-api/__tests__/kube-api-parse.test.ts index 547f78adef..6d05385a28 100644 --- a/packages/core/src/common/k8s-api/__tests__/kube-api-parse.test.ts +++ b/packages/core/src/common/k8s-api/__tests__/kube-api-parse.test.ts @@ -114,7 +114,7 @@ const tests: KubeApiParseTestData[] = [ }], ]; -const throwtests = [ +const invalidTests = [ undefined, "", "ajklsmh", @@ -125,7 +125,7 @@ describe("parseApi unit tests", () => { expect(parseKubeApi(url)).toStrictEqual(expected); }); - it.each(throwtests)("testing %j should throw", (url) => { - expect(() => parseKubeApi(url as never)).toThrowError("invalid apiPath"); + it.each(invalidTests)("testing %j should throw", (url) => { + expect(parseKubeApi(url as never)).toBe(undefined); }); }); diff --git a/packages/core/src/common/k8s-api/api-manager/api-manager.ts b/packages/core/src/common/k8s-api/api-manager/api-manager.ts index 23574822ed..8e0eff8255 100644 --- a/packages/core/src/common/k8s-api/api-manager/api-manager.ts +++ b/packages/core/src/common/k8s-api/api-manager/api-manager.ts @@ -74,9 +74,13 @@ export class ApiManager { return iter.find(this.apis.values(), pathOrCallback); } - const { apiBase } = parseKubeApi(pathOrCallback); + const parsedApi = parseKubeApi(pathOrCallback); - return this.apis.get(apiBase); + if (!parsedApi) { + return undefined; + } + + return this.apis.get(parsedApi.apiBase); } getApiByKind(kind: string, apiVersion: string) { @@ -141,9 +145,10 @@ export class ApiManager { } const { apiBase } = typeof apiOrBase === "string" - ? parseKubeApi(apiOrBase) + ? parseKubeApi(apiOrBase) ?? {} : apiOrBase; - const api = this.getApi(apiBase); + + const api = apiBase && this.getApi(apiBase); if (!api) { return undefined; diff --git a/packages/core/src/common/k8s-api/kube-api-parse.ts b/packages/core/src/common/k8s-api/kube-api-parse.ts index 522e2812b8..e69d3ffa69 100644 --- a/packages/core/src/common/k8s-api/kube-api-parse.ts +++ b/packages/core/src/common/k8s-api/kube-api-parse.ts @@ -22,16 +22,16 @@ export interface IKubeApiParsed extends IKubeApiLinkRef { apiVersionWithGroup: string; } -export function parseKubeApi(path: string): IKubeApiParsed { +export function parseKubeApi(path: string): IKubeApiParsed | undefined { const apiPath = new URL(path, "https://localhost").pathname; const [, prefix, ...parts] = apiPath.split("/"); const apiPrefix = `/${prefix}`; const [left, right, namespaced] = array.split(parts, "namespaces"); - let apiGroup!: string; - let apiVersion!: string; - let namespace!: string; - let resource!: string; - let name!: string; + let apiGroup: string; + let apiVersion: string | undefined; + let namespace: string | undefined; + let resource: string; + let name: string | undefined; if (namespaced) { switch (right.length) { @@ -46,26 +46,21 @@ export function parseKubeApi(path: string): IKubeApiParsed { break; } - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - apiVersion = left.pop()!; - apiGroup = left.join("/"); + let rest: string[]; + + [apiVersion, ...rest] = left; + apiGroup = rest.join("/"); } else { - switch (left.length) { - case 0: - throw new Error(`invalid apiPath: ${apiPath}`); - case 4: - [apiGroup, apiVersion, resource, name] = left; - break; - case 2: - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - resource = left.pop()!; - // fallthrough - case 1: - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - apiVersion = left.pop()!; - apiGroup = ""; - break; - default: + if (left.length === 0) { + return undefined; + } + + if (left.length === 1 || left.length === 2) { + [apiVersion, resource] = left; + apiGroup = ""; + } else if (left.length === 4) { + [apiGroup, apiVersion, resource, name] = left; + } else { /** * Given that * - `apiVersion` is `GROUP/VERSION` and @@ -82,15 +77,14 @@ export function parseKubeApi(path: string): IKubeApiParsed { * 3. otherwise assume apiVersion <- left[0] * 4. always resource, name <- left[(0 or 1)+1..] */ - if (left[0].includes(".") || left[1].match(/^v[0-9]/)) { - [apiGroup, apiVersion] = left; - resource = left.slice(2).join("/"); - } else { - apiGroup = ""; - apiVersion = left[0]; - [resource, name] = left.slice(1); - } - break; + if (left[0].includes(".") || left[1].match(/^v[0-9]/)) { + [apiGroup, apiVersion] = left; + resource = left.slice(2).join("/"); + } else { + apiGroup = ""; + apiVersion = left[0]; + [resource, name] = left.slice(1); + } } } @@ -98,7 +92,7 @@ export function parseKubeApi(path: string): IKubeApiParsed { const apiBase = [apiPrefix, apiGroup, apiVersion, resource].filter(v => v).join("/"); if (!apiBase) { - throw new Error(`invalid apiPath: ${apiPath}`); + return undefined; } return { @@ -110,7 +104,7 @@ export function parseKubeApi(path: string): IKubeApiParsed { } function isIKubeApiParsed(refOrParsed: IKubeApiLinkRef | IKubeApiParsed): refOrParsed is IKubeApiParsed { - return "apiGroup" in refOrParsed; + return "apiGroup" in refOrParsed && !!refOrParsed.apiGroup; } export function createKubeApiURL(linkRef: IKubeApiLinkRef): string; diff --git a/packages/core/src/common/k8s-api/kube-api.ts b/packages/core/src/common/k8s-api/kube-api.ts index cf9d8f15a7..d10b5b3e51 100644 --- a/packages/core/src/common/k8s-api/kube-api.ts +++ b/packages/core/src/common/k8s-api/kube-api.ts @@ -264,12 +264,16 @@ export class KubeApi< allowedUsableVersions, } = opts; - assert(fullApiPathname, "apiBase MUST be provied either via KubeApiOptions.apiBase or KubeApiOptions.objectConstructor.apiBase"); + assert(fullApiPathname, "apiBase MUST be provided either via KubeApiOptions.apiBase or KubeApiOptions.objectConstructor.apiBase"); assert(request, "request MUST be provided if not in a cluster page frame context"); - const { apiBase, apiPrefix, apiGroup, apiVersion, resource } = parseKubeApi(fullApiPathname); + const parsedApi = parseKubeApi(fullApiPathname); - assert(kind, "kind MUST be provied either via KubeApiOptions.kind or KubeApiOptions.objectConstructor.kind"); + assert(parsedApi, "apiBase MUST be a valid kube api pathname"); + + const { apiBase, apiPrefix, apiGroup, apiVersion, resource } = parsedApi; + + assert(kind, "kind MUST be provided either via KubeApiOptions.kind or KubeApiOptions.objectConstructor.kind"); assert(apiPrefix, "apiBase MUST be parsable as a kubeApi selfLink style string"); this.doCheckPreferredVersion = doCheckPreferredVersion; @@ -308,24 +312,26 @@ export class KubeApi< const apiBases = new Set(rawApiBases); for (const apiUrl of apiBases) { - try { - const { apiPrefix, apiGroup, resource } = parseKubeApi(apiUrl); - const list = await this.request.get(`${apiPrefix}/${apiGroup}`) as KubeApiResourceVersionList; - const resourceVersions = getOrderedVersions(list, this.allowedUsableVersions?.[apiGroup]); + const parsedApi = parseKubeApi(apiUrl); - for (const resourceVersion of resourceVersions) { - const { resources } = await this.request.get(`${apiPrefix}/${resourceVersion.groupVersion}`) as KubeApiResourceList; + if (!parsedApi) { + continue; + } - if (resources.some(({ name }) => name === resource)) { - return { - apiPrefix, - apiGroup, - apiVersionPreferred: resourceVersion.version, - }; - } + const { apiPrefix, apiGroup, resource } = parsedApi; + const list = await this.request.get(`${apiPrefix}/${apiGroup}`) as KubeApiResourceVersionList; + const resourceVersions = getOrderedVersions(list, this.allowedUsableVersions?.[apiGroup]); + + for (const resourceVersion of resourceVersions) { + const { resources } = await this.request.get(`${apiPrefix}/${resourceVersion.groupVersion}`) as KubeApiResourceList; + + if (resources.some(({ name }) => name === resource)) { + return { + apiPrefix, + apiGroup, + apiVersionPreferred: resourceVersion.version, + }; } - } catch (error) { - // Exception is ignored as we can try the next url } } diff --git a/packages/core/src/common/k8s-api/kube-api/get-kube-api-from-path.injectable.ts b/packages/core/src/common/k8s-api/kube-api/get-kube-api-from-path.injectable.ts index 669185684f..61ac7b1e96 100644 --- a/packages/core/src/common/k8s-api/kube-api/get-kube-api-from-path.injectable.ts +++ b/packages/core/src/common/k8s-api/kube-api/get-kube-api-from-path.injectable.ts @@ -7,18 +7,18 @@ import { parseKubeApi } from "../kube-api-parse"; import { kubeApiInjectionToken } from "./kube-api-injection-token"; import type { KubeApi } from "../kube-api"; +export type GetKubeApiFromPath = (apiPath: string) => KubeApi | undefined; + const getKubeApiFromPathInjectable = getInjectable({ id: "get-kube-api-from-path", - instantiate: (di) => { + instantiate: (di): GetKubeApiFromPath => { const kubeApis = di.injectMany(kubeApiInjectionToken); return (apiPath: string) => { const parsed = parseKubeApi(apiPath); - const kubeApi = kubeApis.find((api) => api.apiBase === parsed.apiBase); - - return (kubeApi as KubeApi) || undefined; + return kubeApis.find((api) => api.apiBase === parsed?.apiBase); }; }, }); diff --git a/packages/core/src/common/k8s-api/kube-object.store.ts b/packages/core/src/common/k8s-api/kube-object.store.ts index 9effdc8f57..9efaca4dee 100644 --- a/packages/core/src/common/k8s-api/kube-object.store.ts +++ b/packages/core/src/common/k8s-api/kube-object.store.ts @@ -324,7 +324,11 @@ export class KubeObjectStore< @action async loadFromPath(resourcePath: string) { - const { namespace, name } = parseKubeApi(resourcePath); + const parsedApi = parseKubeApi(resourcePath); + + assert(parsedApi, "resourcePath must be a valid kube api"); + + const { namespace, name } = parsedApi; assert(name, "name must be part of resourcePath"); diff --git a/packages/core/src/features/telemetry/renderer/telemetry-decorator-for-show-details.injectable.ts b/packages/core/src/features/telemetry/renderer/telemetry-decorator-for-show-details.injectable.ts index 39a729bc4d..221bcd36fa 100644 --- a/packages/core/src/features/telemetry/renderer/telemetry-decorator-for-show-details.injectable.ts +++ b/packages/core/src/features/telemetry/renderer/telemetry-decorator-for-show-details.injectable.ts @@ -4,6 +4,7 @@ */ import { getInjectable, createInstantiationTargetDecorator, instantiationDecoratorToken } from "@ogre-tools/injectable"; import { pick } from "lodash"; +import { inspect } from "util"; import { parseKubeApi } from "../../../common/k8s-api/kube-api-parse"; import showDetailsInjectable from "../../../renderer/components/kube-detail-params/show-details.injectable"; import emitTelemetryInjectable from "./emit-telemetry.injectable"; @@ -21,13 +22,15 @@ const telemetryDecoratorForShowDetailsInjectable = getInjectable({ ? { action: "open", ...(() => { - try { - return { - resource: pick(parseKubeApi(args[0]), "apiPrefix", "apiVersion", "apiGroup", "namespace", "resource", "name"), - }; - } catch (error) { - return { error: `${error}` }; + const parsedApi = parseKubeApi(args[0]); + + if (!parsedApi) { + return { error: `invalid apiPath: ${inspect(args[0])}` }; } + + return { + resource: pick(parsedApi, "apiPrefix", "apiVersion", "apiGroup", "namespace", "resource", "name"), + }; })(), } : { diff --git a/packages/core/src/features/telemetry/show-details-calls.test.ts b/packages/core/src/features/telemetry/show-details-calls.test.ts index 736fe13530..ac90d99a87 100644 --- a/packages/core/src/features/telemetry/show-details-calls.test.ts +++ b/packages/core/src/features/telemetry/show-details-calls.test.ts @@ -21,7 +21,7 @@ describe("emit telemetry with params for calls to showDetails", () => { showDetails = di.inject(showDetailsInjectable); }); - it("when showDetails is called with no selflink (ie closing) should emit telemetry with param indicating closing the drawer", () => { + it("when showDetails is called with no selfLink (ie closing) should emit telemetry with param indicating closing the drawer", () => { showDetails(undefined); expect(emitAppEventMock).toBeCalledWith({ @@ -34,7 +34,7 @@ describe("emit telemetry with params for calls to showDetails", () => { }); }); - it("when showDetails is called with empty selflink (ie closing) should emit telemetry with param indicating closing the drawer", () => { + it("when showDetails is called with empty selfLink (ie closing) should emit telemetry with param indicating closing the drawer", () => { showDetails(""); expect(emitAppEventMock).toBeCalledWith({ @@ -47,7 +47,7 @@ describe("emit telemetry with params for calls to showDetails", () => { }); }); - it("when showDetails is called with valid selflink should emit telemetry with param indicating opening the drawer with that resource", () => { + it("when showDetails is called with valid selfLink should emit telemetry with param indicating opening the drawer with that resource", () => { showDetails("/api/v1/namespaces/default/pods/some-name"); expect(emitAppEventMock).toBeCalledWith({ @@ -68,7 +68,7 @@ describe("emit telemetry with params for calls to showDetails", () => { }); }); - it("when showDetails is called with invalid selflink should emit telemetry with param indicating opening the drawer but also show error", () => { + it("when showDetails is called with invalid selfLink should emit telemetry with param indicating opening the drawer but also show error", () => { showDetails("some-non-self-link-value"); expect(emitAppEventMock).toBeCalledWith({ @@ -77,7 +77,7 @@ describe("emit telemetry with params for calls to showDetails", () => { name: "show-details", params: { action: "open", - error: "Error: invalid apiPath: /some-non-self-link-value", + error: "invalid apiPath: 'some-non-self-link-value'", }, }); }); diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts index 42ffa28946..8f66768c9c 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts @@ -20,7 +20,7 @@ const callForResourceInjectable = getInjectable({ return async (apiPath: string) => { const parsed = parseKubeApi(apiPath); - if (!parsed.name) { + if (!parsed?.name) { return { callWasSuccessful: false, error: "Invalid API path" }; } diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx index e1f8eca988..5b5cb352e8 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx @@ -59,11 +59,17 @@ interface Dependencies { readonly tabId: string; } -function getEditSelfLinkFor(object: RawKubeObject): string { +function getEditSelfLinkFor(object: RawKubeObject): string | undefined { const lensVersionLabel = object.metadata.labels?.[EditResourceLabelName]; if (lensVersionLabel) { - const { apiVersionWithGroup, ...parsedApi } = parseKubeApi(object.metadata.selfLink); + const parsedKubeApi = parseKubeApi(object.metadata.selfLink); + + if (!parsedKubeApi) { + return undefined; + } + + const { apiVersionWithGroup, ...parsedApi } = parsedKubeApi; parsedApi.apiVersion = lensVersionLabel; @@ -139,6 +145,10 @@ export class EditResourceModel { if (result?.response?.metadata.labels?.[EditResourceLabelName]) { const parsed = parseKubeApi(this.selfLink); + if (!parsed) { + return void this.dependencies.showErrorNotification(`Object's selfLink is invalid: "${this.selfLink}"`); + } + parsed.apiVersion = result.response.metadata.labels[EditResourceLabelName]; result = await this.dependencies.callForResource(createKubeApiURL(parsed)); @@ -186,6 +196,17 @@ export class EditResourceModel { const patches = createPatch(firstVersion, currentVersion); const selfLink = getEditSelfLinkFor(currentVersion); + + if (!selfLink) { + this.dependencies.showErrorNotification(( +

+ {`Cannot save resource, unknown selfLink: "${currentVersion.metadata.selfLink}"`} +

+ )); + + return null; + } + const result = await this.dependencies.callForPatchResource(this.resource, patches); if (!result.callWasSuccessful) { From 4634643f9338eddb17b34f3f35b5051e2276cbed Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 15:49:08 -0400 Subject: [PATCH 03/16] chore: Cleanup formatting of imports Signed-off-by: Sebastian Malton --- packages/core/src/common/k8s-api/kube-object.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/packages/core/src/common/k8s-api/kube-object.ts b/packages/core/src/common/k8s-api/kube-object.ts index e43633aed6..c1378f5172 100644 --- a/packages/core/src/common/k8s-api/kube-object.ts +++ b/packages/core/src/common/k8s-api/kube-object.ts @@ -26,15 +26,11 @@ import type { ItemObject } from "@k8slens/list-layout"; import type { Patch } from "rfc6902"; import assert from "assert"; import type { JsonObject } from "type-fest"; -import requestKubeObjectPatchInjectable - from "./endpoints/resource-applier.api/request-patch.injectable"; +import requestKubeObjectPatchInjectable from "./endpoints/resource-applier.api/request-patch.injectable"; import { apiKubeInjectionToken } from "./api-kube"; -import requestKubeObjectCreationInjectable - from "./endpoints/resource-applier.api/request-update.injectable"; +import requestKubeObjectCreationInjectable from "./endpoints/resource-applier.api/request-update.injectable"; import { dump } from "js-yaml"; -import { - getLegacyGlobalDiForExtensionApi, -} from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; +import { getLegacyGlobalDiForExtensionApi } from "../../extensions/as-legacy-globals-for-extension-api/legacy-global-di-for-extension-api"; import autoBind from "auto-bind"; export type KubeJsonApiDataFor = K extends KubeObject From bf6af58d80552a16be7a547f772902b138a12fbd Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 15:49:38 -0400 Subject: [PATCH 04/16] fix: Add checks to KubeObject constructor to ensure shape Signed-off-by: Sebastian Malton --- .../core/src/common/k8s-api/kube-object.ts | 20 +++++++++++-- .../__tests__/network-policy-details.test.tsx | 28 ++++++++++++++++--- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/core/src/common/k8s-api/kube-object.ts b/packages/core/src/common/k8s-api/kube-object.ts index c1378f5172..9549cd5917 100644 --- a/packages/core/src/common/k8s-api/kube-object.ts +++ b/packages/core/src/common/k8s-api/kube-object.ts @@ -548,14 +548,30 @@ export class KubeObject< } constructor(data: KubeJsonApiData) { - if (typeof data !== "object") { + if (!isObject(data)) { throw new TypeError(`Cannot create a KubeObject from ${typeof data}`); } - if (!data.metadata || typeof data.metadata !== "object") { + if (!isObject(data.metadata)) { throw new KubeCreationError(`Cannot create a KubeObject from an object without metadata`, data); } + if (!isString(data.metadata.name)) { + throw new KubeCreationError(`Cannot create a KubeObject from an object without metadata.name being a string`, data); + } + + if (!isString(data.metadata.uid)) { + throw new KubeCreationError(`Cannot create a KubeObject from an object without metadata.uid being a string`, data); + } + + if (!isString(data.metadata.resourceVersion)) { + throw new KubeCreationError(`Cannot create a KubeObject from an object without metadata.resourceVersion being a string`, data); + } + + if (!isString(data.metadata.selfLink)) { + throw new KubeCreationError(`Cannot create a KubeObject from an object without metadata.selfLink being a string`, data); + } + Object.assign(this, data); autoBind(this); } diff --git a/packages/core/src/renderer/components/+network-policies/__tests__/network-policy-details.test.tsx b/packages/core/src/renderer/components/+network-policies/__tests__/network-policy-details.test.tsx index b99f41808a..c849a604ac 100644 --- a/packages/core/src/renderer/components/+network-policies/__tests__/network-policy-details.test.tsx +++ b/packages/core/src/renderer/components/+network-policies/__tests__/network-policy-details.test.tsx @@ -22,8 +22,16 @@ describe("NetworkPolicyDetails", () => { it("should render w/o errors", () => { const policy = new NetworkPolicy({ - metadata: {} as never, - spec: {} as never, + metadata: { + name: "some-network-policy-name", + namespace: "some-namespace", + resourceVersion: "1", + selfLink: "/apis/networking.k8s.io/v1/namespace/some-namespace/some-network-policy-name", + uid: "1", + }, + spec: { + podSelector: {}, + }, apiVersion: "networking.k8s.io/v1", kind: "NetworkPolicy", }); @@ -34,7 +42,13 @@ describe("NetworkPolicyDetails", () => { it("should render egress nodeSelector", async () => { const policy = new NetworkPolicy({ - metadata: {} as never, + metadata: { + name: "some-network-policy-name", + namespace: "some-namespace", + resourceVersion: "1", + selfLink: "/apis/networking.k8s.io/v1/namespace/some-namespace/some-network-policy-name", + uid: "1", + }, spec: { egress: [{ to: [{ @@ -58,7 +72,13 @@ describe("NetworkPolicyDetails", () => { it("should not crash if egress nodeSelector doesn't have matchLabels", async () => { const policy = new NetworkPolicy({ - metadata: {} as never, + metadata: { + name: "some-network-policy-name", + namespace: "some-namespace", + resourceVersion: "1", + selfLink: "/apis/networking.k8s.io/v1/namespace/some-namespace/some-network-policy-name", + uid: "1", + }, spec: { egress: [{ to: [{ From 3439472065e6b850e286f6a34bccc23b827b8e28 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 15:49:58 -0400 Subject: [PATCH 05/16] feat: Improve formatting error messages from apiKube Signed-off-by: Sebastian Malton --- packages/core/src/common/utils/get-error-message.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/core/src/common/utils/get-error-message.ts b/packages/core/src/common/utils/get-error-message.ts index b5d7dd4244..84e6c8083a 100644 --- a/packages/core/src/common/utils/get-error-message.ts +++ b/packages/core/src/common/utils/get-error-message.ts @@ -2,6 +2,9 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ + +import { JsonApiErrorParsed } from "../k8s-api/json-api"; + export const getErrorMessage = (error: unknown): string => { if (typeof error === "string") { return error; @@ -11,5 +14,9 @@ export const getErrorMessage = (error: unknown): string => { return error.message; } + if (error instanceof JsonApiErrorParsed) { + return error.toString(); + } + return JSON.stringify(error); }; From 456d6ae94f7d1b68b434778fdf7b4c6d9af1aed4 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 16:01:51 -0400 Subject: [PATCH 06/16] Fix: Correct getEditSelfLinkFor to produce correct selfLink Signed-off-by: Sebastian Malton --- .../edit-resource-model/edit-resource-model.injectable.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx index 5b5cb352e8..db16eb70ca 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx @@ -71,11 +71,9 @@ function getEditSelfLinkFor(object: RawKubeObject): string | undefined { const { apiVersionWithGroup, ...parsedApi } = parsedKubeApi; - parsedApi.apiVersion = lensVersionLabel; - return createKubeApiURL({ ...parsedApi, - apiVersion: `${parsedApi.apiGroup}/${parsedApi.apiVersion}`, + apiVersion: lensVersionLabel, }); } From 6c3e8e83c03d13bd42db4ab3c56ebae5b4b3d649 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 16:04:52 -0400 Subject: [PATCH 07/16] chore: Move files around to flatten hierarchy Signed-off-by: Sebastian Malton --- .../namespaces/edit-namespace-from-new-tab.test.tsx | 8 ++++---- .../edit-namespace-from-previously-opened-tab.test.tsx | 4 ++-- ...l-for-patch-resource.global-override-for-injectable.ts | 0 .../call-for-patch-resource.injectable.ts | 8 ++++---- .../call-for-resource.global-override-for-injectable.ts | 0 .../call-for-resource.injectable.ts | 8 ++++---- .../edit-resource-model.injectable.tsx | 8 ++++---- 7 files changed, 18 insertions(+), 18 deletions(-) rename packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/{call-for-patch-resource => }/call-for-patch-resource.global-override-for-injectable.ts (100%) rename packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/{call-for-patch-resource => }/call-for-patch-resource.injectable.ts (77%) rename packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/{call-for-resource => }/call-for-resource.global-override-for-injectable.ts (100%) rename packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/{call-for-resource => }/call-for-resource.injectable.ts (76%) diff --git a/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx b/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx index 8480da45e3..f5e33dfabc 100644 --- a/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx +++ b/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx @@ -12,8 +12,8 @@ import createEditResourceTabInjectable from "../../../renderer/components/dock/e import getRandomIdForEditResourceTabInjectable from "../../../renderer/components/dock/edit-resource/get-random-id-for-edit-resource-tab.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import type { CallForPatchResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.injectable"; -import callForPatchResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.injectable"; +import type { CallForPatchResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable"; +import callForPatchResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable"; import dockStoreInjectable from "../../../renderer/components/dock/dock/store.injectable"; import { Namespace } from "../../../common/k8s-api/endpoints"; import showSuccessNotificationInjectable from "../../../renderer/components/notifications/show-success-notification.injectable"; @@ -21,8 +21,8 @@ import showErrorNotificationInjectable from "../../../renderer/components/notifi import readJsonFileInjectable from "../../../common/fs/read-json-file.injectable"; import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import hostedClusterIdInjectable from "../../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; -import type { CallForResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable"; -import callForResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable"; +import type { CallForResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable"; +import callForResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable"; describe("cluster/namespaces - edit namespace from new tab", () => { let builder: ApplicationBuilder; diff --git a/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx b/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx index 8e2803a35c..0089b64c47 100644 --- a/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx +++ b/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx @@ -8,8 +8,8 @@ import type { ApplicationBuilder } from "../../../renderer/components/test-utils import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import type { CallForResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable"; -import callForResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable"; +import type { CallForResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable"; +import callForResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable"; import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import writeJsonFileInjectable from "../../../common/fs/write-json-file.injectable"; import { TabKind } from "../../../renderer/components/dock/dock/store"; diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.global-override-for-injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.global-override-for-injectable.ts similarity index 100% rename from packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.global-override-for-injectable.ts rename to packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.global-override-for-injectable.ts diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable.ts similarity index 77% rename from packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.injectable.ts rename to packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable.ts index ddee1e6810..602312380c 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource/call-for-patch-resource.injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable.ts @@ -4,11 +4,11 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { AsyncResult } from "@k8slens/utilities"; -import apiManagerInjectable from "../../../../../../common/k8s-api/api-manager/manager.injectable"; -import type { JsonPatch } from "../../../../../../common/k8s-api/kube-object.store"; -import type { KubeObject } from "../../../../../../common/k8s-api/kube-object"; +import apiManagerInjectable from "../../../../../common/k8s-api/api-manager/manager.injectable"; +import type { JsonPatch } from "../../../../../common/k8s-api/kube-object.store"; +import type { KubeObject } from "../../../../../common/k8s-api/kube-object"; import assert from "assert"; -import { getErrorMessage } from "../../../../../../common/utils/get-error-message"; +import { getErrorMessage } from "../../../../../common/utils/get-error-message"; export type CallForPatchResource = ( item: KubeObject, diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.global-override-for-injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.global-override-for-injectable.ts similarity index 100% rename from packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.global-override-for-injectable.ts rename to packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.global-override-for-injectable.ts diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable.ts similarity index 76% rename from packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts rename to packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable.ts index 8f66768c9c..256a906aa3 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource/call-for-resource.injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable.ts @@ -3,11 +3,11 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import { KubeObject } from "../../../../../../common/k8s-api/kube-object"; -import { parseKubeApi } from "../../../../../../common/k8s-api/kube-api-parse"; +import { KubeObject } from "../../../../../common/k8s-api/kube-object"; +import { parseKubeApi } from "../../../../../common/k8s-api/kube-api-parse"; import type { AsyncResult } from "@k8slens/utilities"; -import { getErrorMessage } from "../../../../../../common/utils/get-error-message"; -import apiKubeInjectable from "../../../../../k8s/api-kube.injectable"; +import { getErrorMessage } from "../../../../../common/utils/get-error-message"; +import apiKubeInjectable from "../../../../k8s/api-kube.injectable"; export type CallForResource = (selfLink: string) => AsyncResult; diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx index db16eb70ca..12f2424268 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import type { CallForResource } from "./call-for-resource/call-for-resource.injectable"; -import callForResourceInjectable from "./call-for-resource/call-for-resource.injectable"; +import type { CallForResource } from "./call-for-resource.injectable"; +import callForResourceInjectable from "./call-for-resource.injectable"; import { waitUntilDefined } from "@k8slens/utilities"; import editResourceTabStoreInjectable from "../store.injectable"; import type { EditingResource, EditResourceTabStore } from "../store"; @@ -12,8 +12,8 @@ import { action, computed, observable, runInAction } from "mobx"; import type { KubeObject, RawKubeObject } from "../../../../../common/k8s-api/kube-object"; import yaml from "js-yaml"; import assert from "assert"; -import type { CallForPatchResource } from "./call-for-patch-resource/call-for-patch-resource.injectable"; -import callForPatchResourceInjectable from "./call-for-patch-resource/call-for-patch-resource.injectable"; +import type { CallForPatchResource } from "./call-for-patch-resource.injectable"; +import callForPatchResourceInjectable from "./call-for-patch-resource.injectable"; import { createPatch } from "rfc6902"; import type { ShowNotification } from "../../../notifications"; import showSuccessNotificationInjectable from "../../../notifications/show-success-notification.injectable"; From 4716dcc43419ea453465879ec21f6cf3d1580948 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 16:08:55 -0400 Subject: [PATCH 08/16] chore: Rename injectables to remove redundancy Signed-off-by: Sebastian Malton --- .../edit-namespace-from-new-tab.test.tsx | 64 +++++++++---------- ...espace-from-previously-opened-tab.test.tsx | 14 ++-- .../edit-resource-model.injectable.tsx | 16 ++--- ...esource.global-override-for-injectable.ts} | 4 +- ...ts => request-kube-resource.injectable.ts} | 10 +-- ...esource.global-override-for-injectable.ts} | 4 +- ...request-patch-kube-resource.injectable.ts} | 10 +-- 7 files changed, 61 insertions(+), 61 deletions(-) rename packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/{call-for-resource.global-override-for-injectable.ts => request-kube-resource.global-override-for-injectable.ts} (65%) rename packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/{call-for-resource.injectable.ts => request-kube-resource.injectable.ts} (80%) rename packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/{call-for-patch-resource.global-override-for-injectable.ts => request-patch-kube-resource.global-override-for-injectable.ts} (63%) rename packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/{call-for-patch-resource.injectable.ts => request-patch-kube-resource.injectable.ts} (84%) diff --git a/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx b/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx index f5e33dfabc..f1df8e3a34 100644 --- a/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx +++ b/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx @@ -12,8 +12,8 @@ import createEditResourceTabInjectable from "../../../renderer/components/dock/e import getRandomIdForEditResourceTabInjectable from "../../../renderer/components/dock/edit-resource/get-random-id-for-edit-resource-tab.injectable"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import type { CallForPatchResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable"; -import callForPatchResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable"; +import type { RequestPatchKubeResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.injectable"; +import requestPatchKubeResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.injectable"; import dockStoreInjectable from "../../../renderer/components/dock/dock/store.injectable"; import { Namespace } from "../../../common/k8s-api/endpoints"; import showSuccessNotificationInjectable from "../../../renderer/components/notifications/show-success-notification.injectable"; @@ -21,13 +21,13 @@ import showErrorNotificationInjectable from "../../../renderer/components/notifi import readJsonFileInjectable from "../../../common/fs/read-json-file.injectable"; import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import hostedClusterIdInjectable from "../../../renderer/cluster-frame-context/hosted-cluster-id.injectable"; -import type { CallForResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable"; -import callForResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable"; +import type { RequestKubeResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable"; +import requestKubeResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable"; describe("cluster/namespaces - edit namespace from new tab", () => { let builder: ApplicationBuilder; - let callForResourceMock: AsyncFnMock; - let callForPatchResourceMock: AsyncFnMock; + let requestKubeResourceMock: AsyncFnMock; + let requestPatchKubeResourceMock: AsyncFnMock; let showSuccessNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock; @@ -57,11 +57,11 @@ describe("cluster/namespaces - edit namespace from new tab", () => { .mockReturnValueOnce("some-second-tab-id"), ); - callForResourceMock = asyncFn(); - windowDi.override(callForResourceInjectable, () => callForResourceMock); + requestKubeResourceMock = asyncFn(); + windowDi.override(requestKubeResourceInjectable, () => requestKubeResourceMock); - callForPatchResourceMock = asyncFn(); - windowDi.override(callForPatchResourceInjectable, () => callForPatchResourceMock); + requestPatchKubeResourceMock = asyncFn(); + windowDi.override(requestPatchKubeResourceInjectable, () => requestPatchKubeResourceMock); }); builder.afterWindowStart(() => { @@ -156,7 +156,7 @@ describe("cluster/namespaces - edit namespace from new tab", () => { }); it("calls for namespace", () => { - expect(callForResourceMock).toHaveBeenCalledWith( + expect(requestKubeResourceMock).toHaveBeenCalledWith( "/apis/some-api-version/namespaces/some-uid", ); }); @@ -179,7 +179,7 @@ describe("cluster/namespaces - edit namespace from new tab", () => { }, }); - await callForResourceMock.resolve({ + await requestKubeResourceMock.resolve({ callWasSuccessful: true, response: someNamespace, }); @@ -226,7 +226,7 @@ metadata: }); it("calls for save with just the adding version label", () => { - expect(callForPatchResourceMock).toHaveBeenCalledWith( + expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( someNamespace, [{ op: "add", @@ -262,7 +262,7 @@ metadata: describe("when saving resolves with success", () => { beforeEach(async () => { - await callForPatchResourceMock.resolve({ + await requestPatchKubeResourceMock.resolve({ callWasSuccessful: true, response: { name: "some-name", kind: "Namespace" }, }); @@ -311,7 +311,7 @@ metadata: describe("when saving resolves with failure", () => { beforeEach(async () => { - await callForPatchResourceMock.resolve({ + await requestPatchKubeResourceMock.resolve({ callWasSuccessful: false, error: "some-error", }); @@ -380,7 +380,7 @@ metadata: describe("when saving resolves with success", () => { beforeEach(async () => { - await callForPatchResourceMock.resolve({ + await requestPatchKubeResourceMock.resolve({ callWasSuccessful: true, response: { name: "some-name", kind: "Namespace" }, }); @@ -399,7 +399,7 @@ metadata: describe("when saving resolves with failure", () => { beforeEach(async () => { - await callForPatchResourceMock.resolve({ + await requestPatchKubeResourceMock.resolve({ callWasSuccessful: false, error: "Some error", }); @@ -526,7 +526,7 @@ metadata: }); it("calls for save with changed configuration", () => { - expect(callForPatchResourceMock).toHaveBeenCalledWith( + expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( someNamespace, [ { @@ -555,7 +555,7 @@ metadata: }); it("given save resolves and another change in configuration, when saving, calls for save with changed configuration", async () => { - await callForPatchResourceMock.resolve({ + await requestPatchKubeResourceMock.resolve({ callWasSuccessful: true, response: { @@ -585,7 +585,7 @@ metadata: }); - callForPatchResourceMock.mockClear(); + requestPatchKubeResourceMock.mockClear(); const saveButton = rendered.getByTestId( "save-edit-resource-from-tab-for-some-first-tab-id", @@ -593,7 +593,7 @@ metadata: fireEvent.click(saveButton); - expect(callForPatchResourceMock).toHaveBeenCalledWith( + expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( someNamespace, [ { @@ -692,7 +692,7 @@ metadata: describe("given clicking the context menu for second namespace, when clicking to edit namespace", () => { beforeEach(() => { - callForResourceMock.mockClear(); + requestKubeResourceMock.mockClear(); // TODO: Make implementation match the description const namespaceStub = new Namespace(someOtherNamespaceDataStub); @@ -725,7 +725,7 @@ metadata: }); it("calls for second namespace", () => { - expect(callForResourceMock).toHaveBeenCalledWith( + expect(requestKubeResourceMock).toHaveBeenCalledWith( "/apis/some-api-version/namespaces/some-other-uid", ); }); @@ -747,7 +747,7 @@ metadata: }, }); - await callForResourceMock.resolve({ + await requestKubeResourceMock.resolve({ callWasSuccessful: true, response: someOtherNamespace, }); @@ -773,7 +773,7 @@ metadata: }); it("when selecting to save, calls for save of second namespace with just the add edit version label", () => { - callForPatchResourceMock.mockClear(); + requestPatchKubeResourceMock.mockClear(); const saveButton = rendered.getByTestId( "save-edit-resource-from-tab-for-some-second-tab-id", @@ -781,7 +781,7 @@ metadata: fireEvent.click(saveButton); - expect(callForPatchResourceMock).toHaveBeenCalledWith( + expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( someOtherNamespace, [{ op: "add", @@ -795,7 +795,7 @@ metadata: describe("when clicking dock tab for the first namespace", () => { beforeEach(() => { - callForResourceMock.mockClear(); + requestKubeResourceMock.mockClear(); const tab = rendered.getByTestId("dock-tab-for-some-first-tab-id"); @@ -825,7 +825,7 @@ metadata: }); it("does not call for namespace", () => { - expect(callForResourceMock).not.toHaveBeenCalledWith("/apis/some-api-version/namespaces/some-uid"); + expect(requestKubeResourceMock).not.toHaveBeenCalledWith("/apis/some-api-version/namespaces/some-uid"); }); it("has configuration in the editor", () => { @@ -846,7 +846,7 @@ metadata: }); it("when selecting to save, calls for save of first namespace with just the new edit version label", () => { - callForPatchResourceMock.mockClear(); + requestPatchKubeResourceMock.mockClear(); const saveButton = rendered.getByTestId( "save-edit-resource-from-tab-for-some-first-tab-id", @@ -854,7 +854,7 @@ metadata: fireEvent.click(saveButton); - expect(callForPatchResourceMock).toHaveBeenCalledWith( + expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( someNamespace, [ { op: "add", @@ -872,7 +872,7 @@ metadata: describe("when call for namespace resolves without namespace", () => { beforeEach(async () => { - await callForResourceMock.resolve({ + await requestKubeResourceMock.resolve({ callWasSuccessful: true, response: undefined, }); @@ -901,7 +901,7 @@ metadata: describe("when call for namespace resolves with failure", () => { beforeEach(async () => { - await callForResourceMock.resolve({ + await requestKubeResourceMock.resolve({ callWasSuccessful: false, error: "some-error", }); diff --git a/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx b/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx index 0089b64c47..07a907ac82 100644 --- a/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx +++ b/packages/core/src/features/cluster/namespaces/edit-namespace-from-previously-opened-tab.test.tsx @@ -8,8 +8,8 @@ import type { ApplicationBuilder } from "../../../renderer/components/test-utils import { getApplicationBuilder } from "../../../renderer/components/test-utils/get-application-builder"; import type { AsyncFnMock } from "@async-fn/jest"; import asyncFn from "@async-fn/jest"; -import type { CallForResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable"; -import callForResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable"; +import type { RequestKubeResource } from "../../../renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable"; +import requestKubeResourceInjectable from "../../../renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable"; import directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; import writeJsonFileInjectable from "../../../common/fs/write-json-file.injectable"; import { TabKind } from "../../../renderer/components/dock/dock/store"; @@ -17,14 +17,14 @@ import { Namespace } from "../../../common/k8s-api/endpoints"; describe("cluster/namespaces - edit namespaces from previously opened tab", () => { let builder: ApplicationBuilder; - let callForNamespaceMock: AsyncFnMock; + let requestKubeResourceMock: AsyncFnMock; beforeEach(() => { builder = getApplicationBuilder(); builder.setEnvironmentToClusterFrame(); - callForNamespaceMock = asyncFn(); + requestKubeResourceMock = asyncFn(); builder.beforeWindowStart(({ windowDi }) => { windowDi.override( @@ -32,7 +32,7 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () = () => "/some-directory-for-lens-local-storage", ); - windowDi.override(callForResourceInjectable, () => callForNamespaceMock); + windowDi.override(requestKubeResourceInjectable, () => requestKubeResourceMock); }); builder.afterWindowStart(() => { @@ -97,7 +97,7 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () = }); it("calls for namespace", () => { - expect(callForNamespaceMock).toHaveBeenCalledWith( + expect(requestKubeResourceMock).toHaveBeenCalledWith( "/apis/some-api-version/namespaces/some-uid", ); }); @@ -122,7 +122,7 @@ describe("cluster/namespaces - edit namespaces from previously opened tab", () = // TODO: Figure out why act is needed here. In CI it works without it. await act(async () => { - await callForNamespaceMock.resolve({ + await requestKubeResourceMock.resolve({ callWasSuccessful: true, response: someNamespace, }); diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx index 12f2424268..7dcba54d01 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx @@ -3,8 +3,8 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable"; -import type { CallForResource } from "./call-for-resource.injectable"; -import callForResourceInjectable from "./call-for-resource.injectable"; +import type { RequestKubeResource } from "./request-kube-resource.injectable"; +import requestKubeResourceInjectable from "./request-kube-resource.injectable"; import { waitUntilDefined } from "@k8slens/utilities"; import editResourceTabStoreInjectable from "../store.injectable"; import type { EditingResource, EditResourceTabStore } from "../store"; @@ -12,8 +12,8 @@ import { action, computed, observable, runInAction } from "mobx"; import type { KubeObject, RawKubeObject } from "../../../../../common/k8s-api/kube-object"; import yaml from "js-yaml"; import assert from "assert"; -import type { CallForPatchResource } from "./call-for-patch-resource.injectable"; -import callForPatchResourceInjectable from "./call-for-patch-resource.injectable"; +import type { RequestPatchKubeResource } from "./request-patch-kube-resource.injectable"; +import requestPatchKubeResourceInjectable from "./request-patch-kube-resource.injectable"; import { createPatch } from "rfc6902"; import type { ShowNotification } from "../../../notifications"; import showSuccessNotificationInjectable from "../../../notifications/show-success-notification.injectable"; @@ -28,8 +28,8 @@ const editResourceModelInjectable = getInjectable({ const store = di.inject(editResourceTabStoreInjectable); const model = new EditResourceModel({ - callForResource: di.inject(callForResourceInjectable), - callForPatchResource: di.inject(callForPatchResourceInjectable), + callForResource: di.inject(requestKubeResourceInjectable), + callForPatchResource: di.inject(requestPatchKubeResourceInjectable), showSuccessNotification: di.inject(showSuccessNotificationInjectable), showErrorNotification: di.inject(showErrorNotificationInjectable), store, @@ -50,8 +50,8 @@ const editResourceModelInjectable = getInjectable({ export default editResourceModelInjectable; interface Dependencies { - callForResource: CallForResource; - callForPatchResource: CallForPatchResource; + callForResource: RequestKubeResource; + callForPatchResource: RequestPatchKubeResource; waitForEditingResource: () => Promise; showSuccessNotification: ShowNotification; showErrorNotification: ShowNotification; diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.global-override-for-injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.global-override-for-injectable.ts similarity index 65% rename from packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.global-override-for-injectable.ts rename to packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.global-override-for-injectable.ts index 6eca686d3f..9755ea309a 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.global-override-for-injectable.ts @@ -3,9 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getGlobalOverride } from "@k8slens/test-utils"; -import callForResourceInjectable from "./call-for-resource.injectable"; +import requestKubeResourceInjectable from "./request-kube-resource.injectable"; -export default getGlobalOverride(callForResourceInjectable, () => () => { +export default getGlobalOverride(requestKubeResourceInjectable, () => () => { throw new Error( "Tried to call for kube resource without explicit override.", ); diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable.ts similarity index 80% rename from packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable.ts rename to packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable.ts index 256a906aa3..01ca26f938 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-resource.injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable.ts @@ -9,12 +9,12 @@ import type { AsyncResult } from "@k8slens/utilities"; import { getErrorMessage } from "../../../../../common/utils/get-error-message"; import apiKubeInjectable from "../../../../k8s/api-kube.injectable"; -export type CallForResource = (selfLink: string) => AsyncResult; +export type RequestKubeResource = (selfLink: string) => AsyncResult; -const callForResourceInjectable = getInjectable({ - id: "call-for-resource", +const requestKubeResourceInjectable = getInjectable({ + id: "request-kube-resource", - instantiate: (di): CallForResource => { + instantiate: (di): RequestKubeResource => { const apiKube = di.inject(apiKubeInjectable); return async (apiPath: string) => { @@ -38,4 +38,4 @@ const callForResourceInjectable = getInjectable({ causesSideEffects: true, }); -export default callForResourceInjectable; +export default requestKubeResourceInjectable; diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.global-override-for-injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.global-override-for-injectable.ts similarity index 63% rename from packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.global-override-for-injectable.ts rename to packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.global-override-for-injectable.ts index c85ebb53cd..c3200b6fac 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.global-override-for-injectable.ts @@ -3,9 +3,9 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getGlobalOverride } from "@k8slens/test-utils"; -import callForPatchResourceInjectable from "./call-for-patch-resource.injectable"; +import requestPatchKubeResourceInjectable from "./request-patch-kube-resource.injectable"; -export default getGlobalOverride(callForPatchResourceInjectable, () => () => { +export default getGlobalOverride(requestPatchKubeResourceInjectable, () => () => { throw new Error( "Tried to call patching of kube resource without explicit override.", ); diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.injectable.ts similarity index 84% rename from packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable.ts rename to packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.injectable.ts index 602312380c..1636d74fa7 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/call-for-patch-resource.injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.injectable.ts @@ -10,14 +10,14 @@ import type { KubeObject } from "../../../../../common/k8s-api/kube-object"; import assert from "assert"; import { getErrorMessage } from "../../../../../common/utils/get-error-message"; -export type CallForPatchResource = ( +export type RequestPatchKubeResource = ( item: KubeObject, patch: JsonPatch ) => AsyncResult<{ name: string; kind: string }>; -const callForPatchResourceInjectable = getInjectable({ - id: "call-for-patch-resource", - instantiate: (di): CallForPatchResource => { +const requestPatchKubeResourceInjectable = getInjectable({ + id: "request-patch-kube-resource", + instantiate: (di): RequestPatchKubeResource => { const apiManager = di.inject(apiManagerInjectable); return async (item, patch) => { @@ -46,4 +46,4 @@ const callForPatchResourceInjectable = getInjectable({ causesSideEffects: true, }); -export default callForPatchResourceInjectable; +export default requestPatchKubeResourceInjectable; From 5fb08960fe36f3e1b814473d5a8e8facafa7aab4 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 16:10:23 -0400 Subject: [PATCH 09/16] chore: Simplify global overrides of requestKubeResource and requestPatchKubeResource Signed-off-by: Sebastian Malton --- ...equest-kube-resource.global-override-for-injectable.ts | 8 ++------ ...-patch-kube-resource.global-override-for-injectable.ts | 8 ++------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.global-override-for-injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.global-override-for-injectable.ts index 9755ea309a..a06b750848 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.global-override-for-injectable.ts @@ -2,11 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "@k8slens/test-utils"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import requestKubeResourceInjectable from "./request-kube-resource.injectable"; -export default getGlobalOverride(requestKubeResourceInjectable, () => () => { - throw new Error( - "Tried to call for kube resource without explicit override.", - ); -}); +export default getGlobalOverrideForFunction(requestKubeResourceInjectable); diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.global-override-for-injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.global-override-for-injectable.ts index c3200b6fac..840f04360d 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.global-override-for-injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.global-override-for-injectable.ts @@ -2,11 +2,7 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ -import { getGlobalOverride } from "@k8slens/test-utils"; +import { getGlobalOverrideForFunction } from "@k8slens/test-utils"; import requestPatchKubeResourceInjectable from "./request-patch-kube-resource.injectable"; -export default getGlobalOverride(requestPatchKubeResourceInjectable, () => () => { - throw new Error( - "Tried to call patching of kube resource without explicit override.", - ); -}); +export default getGlobalOverrideForFunction(requestPatchKubeResourceInjectable); From b90e04e02dfd18896d5f08f1bc36f90179635797 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 16:13:46 -0400 Subject: [PATCH 10/16] fix: Fix selfLink being missing from requestKubeResource Signed-off-by: Sebastian Malton --- .../request-kube-resource.injectable.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable.ts index 01ca26f938..ea0581c6d4 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.injectable.ts @@ -3,11 +3,14 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; +import type { KubeObjectMetadata, KubeObjectScope } from "../../../../../common/k8s-api/kube-object"; import { KubeObject } from "../../../../../common/k8s-api/kube-object"; -import { parseKubeApi } from "../../../../../common/k8s-api/kube-api-parse"; import type { AsyncResult } from "@k8slens/utilities"; import { getErrorMessage } from "../../../../../common/utils/get-error-message"; import apiKubeInjectable from "../../../../k8s/api-kube.injectable"; +import type { Writable } from "type-fest"; +import type { KubeJsonApiData } from "../../../../../common/k8s-api/kube-json-api"; +import { parseKubeApi } from "../../../../../common/k8s-api/kube-api-parse"; export type RequestKubeResource = (selfLink: string) => AsyncResult; @@ -17,17 +20,21 @@ const requestKubeResourceInjectable = getInjectable({ instantiate: (di): RequestKubeResource => { const apiKube = di.inject(apiKubeInjectable); - return async (apiPath: string) => { - const parsed = parseKubeApi(apiPath); + return async (selfLink) => { + const parsed = parseKubeApi(selfLink); if (!parsed?.name) { return { callWasSuccessful: false, error: "Invalid API path" }; } try { + const rawData = await apiKube.get(selfLink) as KubeJsonApiData, unknown, unknown>; + + (rawData.metadata as Writable).selfLink = selfLink; + return { callWasSuccessful: true, - response: new KubeObject(await apiKube.get(apiPath)), + response: new KubeObject(rawData), }; } catch (e) { return { callWasSuccessful: false, error: getErrorMessage(e) }; From bc149f0627833cf2a481eac7215dbec40b30ca05 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 20 Apr 2023 16:14:08 -0400 Subject: [PATCH 11/16] chore: Simplify requestPatchKubeResource impl Signed-off-by: Sebastian Malton --- .../edit-namespace-from-new-tab.test.tsx | 10 ++--- .../edit-resource-model.injectable.tsx | 2 +- .../request-patch-kube-resource.injectable.ts | 38 ++++++++----------- 3 files changed, 22 insertions(+), 28 deletions(-) diff --git a/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx b/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx index f1df8e3a34..a94ad05a23 100644 --- a/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx +++ b/packages/core/src/features/cluster/namespaces/edit-namespace-from-new-tab.test.tsx @@ -227,7 +227,7 @@ metadata: it("calls for save with just the adding version label", () => { expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( - someNamespace, + "/apis/some-api-version/namespaces/some-uid", [{ op: "add", path: "/metadata/labels", @@ -527,7 +527,7 @@ metadata: it("calls for save with changed configuration", () => { expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( - someNamespace, + "/apis/some-api-version/namespaces/some-uid", [ { op: "remove", @@ -594,7 +594,7 @@ metadata: fireEvent.click(saveButton); expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( - someNamespace, + "/apis/some-api-version/namespaces/some-uid", [ { op: "add", @@ -782,7 +782,7 @@ metadata: fireEvent.click(saveButton); expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( - someOtherNamespace, + "/apis/some-api-version/namespaces/some-other-uid", [{ op: "add", path: "/metadata/labels", @@ -855,7 +855,7 @@ metadata: fireEvent.click(saveButton); expect(requestPatchKubeResourceMock).toHaveBeenCalledWith( - someNamespace, + "/apis/some-api-version/namespaces/some-uid", [ { op: "add", path: "/metadata/labels", diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx index 7dcba54d01..30ceae1f6a 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/edit-resource-model.injectable.tsx @@ -205,7 +205,7 @@ export class EditResourceModel { return null; } - const result = await this.dependencies.callForPatchResource(this.resource, patches); + const result = await this.dependencies.callForPatchResource(selfLink, patches); if (!result.callWasSuccessful) { this.dependencies.showErrorNotification(( diff --git a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.injectable.ts b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.injectable.ts index 1636d74fa7..0eac05a43f 100644 --- a/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.injectable.ts +++ b/packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.injectable.ts @@ -4,42 +4,36 @@ */ import { getInjectable } from "@ogre-tools/injectable"; import type { AsyncResult } from "@k8slens/utilities"; -import apiManagerInjectable from "../../../../../common/k8s-api/api-manager/manager.injectable"; import type { JsonPatch } from "../../../../../common/k8s-api/kube-object.store"; -import type { KubeObject } from "../../../../../common/k8s-api/kube-object"; -import assert from "assert"; import { getErrorMessage } from "../../../../../common/utils/get-error-message"; +import apiKubeInjectable from "../../../../k8s/api-kube.injectable"; +import { patchTypeHeaders } from "../../../../../common/k8s-api/kube-api"; -export type RequestPatchKubeResource = ( - item: KubeObject, - patch: JsonPatch -) => AsyncResult<{ name: string; kind: string }>; +export type RequestPatchKubeResource = (selfLink: string, patch: JsonPatch) => AsyncResult<{ name: string; kind: string }>; const requestPatchKubeResourceInjectable = getInjectable({ id: "request-patch-kube-resource", instantiate: (di): RequestPatchKubeResource => { - const apiManager = di.inject(apiManagerInjectable); - - return async (item, patch) => { - const store = apiManager.getStore(item.selfLink); - - assert(store); - - let kubeObject: KubeObject; + const apiKube = di.inject(apiKubeInjectable); + return async (selfLink, patch) => { try { - kubeObject = await store.patch(item, patch); - } catch (e: any) { + const kubeObject = await apiKube.patch(selfLink, { data: patch }, { + headers: { + "content-type": patchTypeHeaders.json, + }, + }); + + return { + callWasSuccessful: true, + response: { name: kubeObject.metadata.name, kind: kubeObject.kind }, + }; + } catch (e) { return { callWasSuccessful: false, error: getErrorMessage(e), }; } - - return { - callWasSuccessful: true, - response: { name: kubeObject.getName(), kind: kubeObject.kind }, - }; }; }, From 5dc94f291bae131ca3fe74f3c13d4c7230e1fc05 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Fri, 21 Apr 2023 09:41:51 -0400 Subject: [PATCH 12/16] chore: Update tests to use more business logic - To have a higher confidence in the code, given that the old tests didn't save us from modifying the code before. Signed-off-by: Sebastian Malton --- .../edit-namespace-from-new-tab.test.tsx.snap | 703 +----------------- .../edit-namespace-from-new-tab.test.tsx | 272 ++++--- .../edit-resource-model.injectable.tsx | 14 +- ...resource.global-override-for-injectable.ts | 8 - .../request-kube-resource.injectable.ts | 8 +- ...resource.global-override-for-injectable.ts | 8 - .../request-patch-kube-resource.injectable.ts | 10 +- .../renderer/k8s/api-kube-get.injectable.ts | 20 + .../renderer/k8s/api-kube-patch.injectable.ts | 20 + 9 files changed, 197 insertions(+), 866 deletions(-) delete mode 100644 packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-kube-resource.global-override-for-injectable.ts delete mode 100644 packages/core/src/renderer/components/dock/edit-resource/edit-resource-model/request-patch-kube-resource.global-override-for-injectable.ts create mode 100644 packages/core/src/renderer/k8s/api-kube-get.injectable.ts create mode 100644 packages/core/src/renderer/k8s/api-kube-patch.injectable.ts diff --git a/packages/core/src/features/cluster/namespaces/__snapshots__/edit-namespace-from-new-tab.test.tsx.snap b/packages/core/src/features/cluster/namespaces/__snapshots__/edit-namespace-from-new-tab.test.tsx.snap index 266fef88c4..be7ad3680d 100644 --- a/packages/core/src/features/cluster/namespaces/__snapshots__/edit-namespace-from-new-tab.test.tsx.snap +++ b/packages/core/src/features/cluster/namespaces/__snapshots__/edit-namespace-from-new-tab.test.tsx.snap @@ -2099,9 +2099,9 @@ metadata: uid: some-uid name: some-name resourceVersion: some-resource-version - selfLink: /apis/some-api-version/namespaces/some-uid somePropertyToBeChanged: some-changed-value someAddedProperty: some-new-value + selfLink: /apis/some-api-version/namespaces/some-uid @@ -4435,9 +4435,9 @@ metadata: uid: some-uid name: some-name resourceVersion: some-resource-version - selfLink: /apis/some-api-version/namespaces/some-uid somePropertyToBeRemoved: some-value somePropertyToBeChanged: some-old-value + selfLink: /apis/some-api-version/namespaces/some-uid @@ -5962,9 +5962,9 @@ metadata: uid: some-uid name: some-name resourceVersion: some-resource-version - selfLink: /apis/some-api-version/namespaces/some-uid somePropertyToBeRemoved: some-value somePropertyToBeChanged: some-old-value + selfLink: /apis/some-api-version/namespaces/some-uid @@ -5976,7 +5976,7 @@ metadata: `; -exports[`cluster/namespaces - edit namespace from new tab when navigating to namespaces when namespaces resolve when clicking the context menu for a namespace when clicking to edit namespace when call for namespace resolves with namespace given no changes in the configuration, when selecting to save when saving resolves with failure renders 1`] = ` +exports[`cluster/namespaces - edit namespace from new tab when navigating to namespaces when namespaces resolve when clicking the context menu for a namespace when clicking to edit namespace when call for namespace resolves with namespace given no changes in the configuration, when selecting to save when saving fails renders 1`] = `
@@ -7466,9 +7466,9 @@ metadata: uid: some-uid name: some-name resourceVersion: some-resource-version - selfLink: /apis/some-api-version/namespaces/some-uid somePropertyToBeRemoved: some-value somePropertyToBeChanged: some-old-value + selfLink: /apis/some-api-version/namespaces/some-uid labels: k8slens-edit-resource-version: some-api-version @@ -8220,9 +8220,9 @@ metadata: uid: some-uid name: some-name resourceVersion: some-resource-version - selfLink: /apis/some-api-version/namespaces/some-uid somePropertyToBeRemoved: some-value somePropertyToBeChanged: some-old-value + selfLink: /apis/some-api-version/namespaces/some-uid
@@ -9568,9 +9568,9 @@ metadata: uid: some-uid name: some-name resourceVersion: some-resource-version - selfLink: /apis/some-api-version/namespaces/some-uid somePropertyToBeRemoved: some-value somePropertyToBeChanged: some-old-value + selfLink: /apis/some-api-version/namespaces/some-uid @@ -9582,7 +9582,7 @@ metadata: `; -exports[`cluster/namespaces - edit namespace from new tab when navigating to namespaces when namespaces resolve when clicking the context menu for a namespace when clicking to edit namespace when call for namespace resolves with namespace when selecting to save and close when saving resolves with failure renders 1`] = ` +exports[`cluster/namespaces - edit namespace from new tab when navigating to namespaces when namespaces resolve when clicking the context menu for a namespace when clicking to edit namespace when call for namespace resolves with namespace when selecting to save and close when saving failings renders 1`] = `
@@ -10920,686 +10920,3 @@ exports[`cluster/namespaces - edit namespace from new tab when navigating to nam
`; - -exports[`cluster/namespaces - edit namespace from new tab when navigating to namespaces when namespaces resolve when clicking the context menu for a namespace when clicking to edit namespace when call for namespace resolves without namespace renders 1`] = ` - -
-
-
-
-
- -
- - - close - - -
- Close -
-
-
-
-
-
-
-
-