mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
chore: Improve linting within @k8slens/core
- Turning on @typescript-eslint/recommended-requiring-type-checking - Turning off @typescript-eslint/no-unnecessary-type-assertion (due too many false positives) - Making @typescript-eslint/no-explicit-any an error (except in tests) Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
6184c2f03b
commit
fa44b795d4
@ -95,7 +95,7 @@ The properties of the `clusterPages` array objects are defined as follows:
|
||||
|
||||
- `id` is a string that identifies the page.
|
||||
- `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
||||
- `Page` is of type ` React.ComponentType<any>`.
|
||||
- `Page` is of type ` React.ComponentType<Record<string, never>>`.
|
||||
It offers flexibility in defining the appearance and behavior of your page.
|
||||
|
||||
`ExamplePage` in the example above can be defined in `page.tsx`:
|
||||
@ -304,7 +304,7 @@ The properties of the `globalPages` array objects are defined as follows:
|
||||
|
||||
- `id` is a string that identifies the page.
|
||||
- `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
||||
- `Page` is of type `React.ComponentType<any>`.
|
||||
- `Page` is of type `React.ComponentType<Record<string, never>>`.
|
||||
It offers flexibility in defining the appearance and behavior of your page.
|
||||
|
||||
`HelpPage` in the example above can be defined in `page.tsx`:
|
||||
|
||||
27983
package-lock.json
generated
27983
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,6 +12,7 @@ module.exports = {
|
||||
"**/static/**/*",
|
||||
"**/site/**/*",
|
||||
"**/build/webpack/**/*",
|
||||
"**/webpack/**/*",
|
||||
],
|
||||
settings: {
|
||||
react: {
|
||||
@ -106,6 +107,7 @@ module.exports = {
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
"plugin:react/recommended",
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/typescript",
|
||||
@ -116,8 +118,8 @@ module.exports = {
|
||||
"react-hooks",
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2018,
|
||||
sourceType: "module",
|
||||
project: true,
|
||||
tsconfigRootDir: "./tsconfig.json",
|
||||
},
|
||||
rules: {
|
||||
"no-constant-condition": ["error", {
|
||||
@ -126,19 +128,14 @@ module.exports = {
|
||||
"header/header": [2, "../../license-header"],
|
||||
"react/prop-types": "off",
|
||||
"no-invalid-this": "off",
|
||||
"@typescript-eslint/no-invalid-this": ["error"],
|
||||
"@typescript-eslint/no-invalid-this": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/interface-name-prefix": "off",
|
||||
"@typescript-eslint/no-use-before-define": "off",
|
||||
"@typescript-eslint/no-empty-interface": "off",
|
||||
"@typescript-eslint/no-var-requires": "off",
|
||||
"@typescript-eslint/ban-ts-ignore": "off",
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/ban-types": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "off",
|
||||
"no-restricted-imports": ["error", {
|
||||
"paths": [
|
||||
{
|
||||
@ -186,6 +183,11 @@ module.exports = {
|
||||
"named": "never",
|
||||
"asyncArrow": "always",
|
||||
}],
|
||||
"@typescript-eslint/restrict-template-expressions": ["error", {
|
||||
"allowNumber": true,
|
||||
"allowBoolean": true,
|
||||
"allowNever": true,
|
||||
}],
|
||||
"@typescript-eslint/naming-convention": ["error",
|
||||
{
|
||||
"selector": "interface",
|
||||
@ -217,7 +219,7 @@ module.exports = {
|
||||
"ignoreRestSiblings": true,
|
||||
},
|
||||
],
|
||||
"comman-dangle": "off",
|
||||
"comma-dangle": "off",
|
||||
"@typescript-eslint/comma-dangle": ["error", "always-multiline"],
|
||||
"comma-spacing": "off",
|
||||
"@typescript-eslint/comma-spacing": "error",
|
||||
@ -296,5 +298,19 @@ module.exports = {
|
||||
}],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: [
|
||||
"**/*.test.ts",
|
||||
"**/*.test.tsx",
|
||||
],
|
||||
plugins: [
|
||||
"jest",
|
||||
],
|
||||
rules: {
|
||||
"@typescript-eslint/unbound-method": "off",
|
||||
"jest/unbound-method": "error",
|
||||
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@ -5,9 +5,7 @@
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import kubectlApplyAllInjectable from "../../main/kubectl/kubectl-apply-all.injectable";
|
||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||
import type { KubernetesCluster } from "../catalog-entities";
|
||||
import readDirectoryInjectable from "../fs/read-directory.injectable";
|
||||
import readFileInjectable from "../fs/read-file.injectable";
|
||||
import { KubernetesCluster } from "../catalog-entities";
|
||||
import createResourceStackInjectable from "../k8s/create-resource-stack.injectable";
|
||||
import appPathsStateInjectable from "../app-paths/app-paths-state.injectable";
|
||||
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
@ -16,26 +14,35 @@ describe("create resource stack tests", () => {
|
||||
let di: DiContainer;
|
||||
let cluster: KubernetesCluster;
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeEach(() => {
|
||||
di = getDiForUnitTesting();
|
||||
cluster = {
|
||||
getId: () => "test-cluster",
|
||||
} as any;
|
||||
cluster = new KubernetesCluster({
|
||||
metadata: {
|
||||
labels: {},
|
||||
name: "some-name",
|
||||
uid: "test-cluster",
|
||||
},
|
||||
spec: {
|
||||
kubeconfigContext: "some-context",
|
||||
kubeconfigPath: "/some-kubeconfig-path",
|
||||
},
|
||||
status: {
|
||||
phase: "some-phase",
|
||||
},
|
||||
});
|
||||
|
||||
di.override(readDirectoryInjectable, () => () => Promise.resolve(["file1"]) as any);
|
||||
di.override(readFileInjectable, () => () => Promise.resolve("filecontents"));
|
||||
di.override(appPathsStateInjectable, () => ({
|
||||
get: () => ({}),
|
||||
}));
|
||||
di.override(directoryForUserDataInjectable, () => "/some-directory-for-user-data");
|
||||
|
||||
|
||||
});
|
||||
|
||||
describe("kubectlApplyFolder", () => {
|
||||
it("returns response", async () => {
|
||||
di.override(kubectlApplyAllInjectable, () => () => Promise.resolve({
|
||||
callWasSuccessful: true as const,
|
||||
response: "success",
|
||||
isOk: true as const,
|
||||
value: "success",
|
||||
}));
|
||||
|
||||
const createResourceStack = di.inject(createResourceStackInjectable);
|
||||
@ -48,7 +55,7 @@ describe("create resource stack tests", () => {
|
||||
|
||||
it("throws on error", async () => {
|
||||
di.override(kubectlApplyAllInjectable, () => () => Promise.resolve({
|
||||
callWasSuccessful: false as const,
|
||||
isOk: false as const,
|
||||
error: "No permissions",
|
||||
}));
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import { KubeConfig } from "@kubernetes/client-node";
|
||||
import assert from "assert";
|
||||
import { validateKubeConfig, loadConfigFromString } from "../kube-helpers";
|
||||
|
||||
const kubeconfig = `
|
||||
@ -63,7 +64,7 @@ interface Kubeconfig {
|
||||
}];
|
||||
kind: string;
|
||||
"current-context": string;
|
||||
preferences: {};
|
||||
preferences: object;
|
||||
}
|
||||
|
||||
let mockKubeConfig: Kubeconfig;
|
||||
@ -78,30 +79,33 @@ describe("kube helpers", () => {
|
||||
describe("with default validation options", () => {
|
||||
describe("with valid kubeconfig", () => {
|
||||
it("does not return an error", () => {
|
||||
expect(validateKubeConfig(kc, "valid")).toBeDefined();
|
||||
expect(validateKubeConfig(kc, "valid").isOk).toBe(true);
|
||||
});
|
||||
});
|
||||
describe("with invalid context object", () => {
|
||||
it("returns an error", () => {
|
||||
expect(validateKubeConfig(kc, "invalid").error?.toString()).toEqual(
|
||||
expect.stringContaining("No valid context object provided in kubeconfig for context 'invalid'"),
|
||||
);
|
||||
const result = validateKubeConfig(kc, "invalid");
|
||||
|
||||
assert(result.isOk === false);
|
||||
expect(result.error).toBe("No valid context object provided in kubeconfig for context 'invalid'");
|
||||
});
|
||||
});
|
||||
|
||||
describe("with invalid cluster object", () => {
|
||||
it("returns an error", () => {
|
||||
expect(validateKubeConfig(kc, "invalidCluster").error?.toString()).toEqual(
|
||||
expect.stringContaining("No valid cluster object provided in kubeconfig for context 'invalidCluster'"),
|
||||
);
|
||||
const result = validateKubeConfig(kc, "invalidCluster");
|
||||
|
||||
assert(result.isOk === false);
|
||||
expect(result.error).toBe("No valid cluster object provided in kubeconfig for context 'invalidCluster'");
|
||||
});
|
||||
});
|
||||
|
||||
describe("with invalid user object", () => {
|
||||
it("returns an error", () => {
|
||||
expect(validateKubeConfig(kc, "invalidUser").error?.toString()).toEqual(
|
||||
expect.stringContaining("No valid user object provided in kubeconfig for context 'invalidUser'"),
|
||||
);
|
||||
const result = validateKubeConfig(kc, "invalidUser");
|
||||
|
||||
assert(result.isOk === false);
|
||||
expect(result.error).toBe("No valid user object provided in kubeconfig for context 'invalidUser'");
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -115,13 +119,15 @@ describe("kube helpers", () => {
|
||||
describe("Check logger.error() output", () => {
|
||||
it("invalid yaml string", () => {
|
||||
const invalidYAMLString = "fancy foo config";
|
||||
const result = loadConfigFromString(invalidYAMLString);
|
||||
|
||||
expect(loadConfigFromString(invalidYAMLString).error).toBeInstanceOf(Error);
|
||||
expect(result.isOk).toBe(false);
|
||||
});
|
||||
it("empty contexts", () => {
|
||||
const emptyContexts = `apiVersion: v1\ncontexts: []`;
|
||||
const result = loadConfigFromString(emptyContexts);
|
||||
|
||||
expect(loadConfigFromString(emptyContexts).error).toBeUndefined();
|
||||
expect(result.isOk).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -151,18 +157,20 @@ describe("kube helpers", () => {
|
||||
};
|
||||
});
|
||||
|
||||
it("single context is ok", async () => {
|
||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
it("single context is ok", () => {
|
||||
const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
|
||||
expect(config.getCurrentContext()).toBe("minikube");
|
||||
assert(result.isOk === true);
|
||||
expect(result.value.getCurrentContext()).toBe("minikube");
|
||||
});
|
||||
|
||||
it("multiple context is ok", async () => {
|
||||
it("multiple context is ok", () => {
|
||||
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "cluster-2" }, name: "cluster-2" });
|
||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
|
||||
expect(config.getCurrentContext()).toBe("minikube");
|
||||
expect(config.contexts.length).toBe(2);
|
||||
assert(result.isOk === true);
|
||||
expect(result.value.getCurrentContext()).toBe("minikube");
|
||||
expect(result.value.contexts.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
@ -192,43 +200,47 @@ describe("kube helpers", () => {
|
||||
};
|
||||
});
|
||||
|
||||
it("empty name in context causes it to be removed", async () => {
|
||||
it("empty name in context causes it to be removed", () => {
|
||||
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "cluster-2" }, name: "" });
|
||||
expect(mockKubeConfig.contexts.length).toBe(2);
|
||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
|
||||
expect(config.getCurrentContext()).toBe("minikube");
|
||||
expect(config.contexts.length).toBe(1);
|
||||
assert(result.isOk === true);
|
||||
expect(result.value.getCurrentContext()).toBe("minikube");
|
||||
expect(result.value.contexts.length).toBe(1);
|
||||
});
|
||||
|
||||
it("empty cluster in context causes it to be removed", async () => {
|
||||
it("empty cluster in context causes it to be removed", () => {
|
||||
mockKubeConfig.contexts.push({ context: { cluster: "", user: "cluster-2" }, name: "cluster-2" });
|
||||
expect(mockKubeConfig.contexts.length).toBe(2);
|
||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
|
||||
expect(config.getCurrentContext()).toBe("minikube");
|
||||
expect(config.contexts.length).toBe(1);
|
||||
assert(result.isOk === true);
|
||||
expect(result.value.getCurrentContext()).toBe("minikube");
|
||||
expect(result.value.contexts.length).toBe(1);
|
||||
});
|
||||
|
||||
it("empty user in context causes it to be removed", async () => {
|
||||
it("empty user in context causes it to be removed", () => {
|
||||
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "" }, name: "cluster-2" });
|
||||
expect(mockKubeConfig.contexts.length).toBe(2);
|
||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
|
||||
expect(config.getCurrentContext()).toBe("minikube");
|
||||
expect(config.contexts.length).toBe(1);
|
||||
assert(result.isOk === true);
|
||||
expect(result.value.getCurrentContext()).toBe("minikube");
|
||||
expect(result.value.contexts.length).toBe(1);
|
||||
});
|
||||
|
||||
it("invalid context in between valid contexts is removed", async () => {
|
||||
it("invalid context in between valid contexts is removed", () => {
|
||||
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "" }, name: "cluster-2" });
|
||||
mockKubeConfig.contexts.push({ context: { cluster: "cluster-3", user: "cluster-3" }, name: "cluster-3" });
|
||||
expect(mockKubeConfig.contexts.length).toBe(3);
|
||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
const result = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||
|
||||
expect(config.getCurrentContext()).toBe("minikube");
|
||||
expect(config.contexts.length).toBe(2);
|
||||
expect(config.contexts[0].name).toBe("minikube");
|
||||
expect(config.contexts[1].name).toBe("cluster-3");
|
||||
assert(result.isOk === true);
|
||||
expect(result.value.getCurrentContext()).toBe("minikube");
|
||||
expect(result.value.contexts.length).toBe(2);
|
||||
expect(result.value.contexts[0].name).toBe("minikube");
|
||||
expect(result.value.contexts[1].name).toBe("cluster-3");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -23,7 +23,7 @@ describe("user store tests", () => {
|
||||
let resetTheme: ResetTheme;
|
||||
let di: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeEach(() => {
|
||||
di = getDiForUnitTesting();
|
||||
|
||||
di.override(writeFileInjectable, () => () => Promise.resolve());
|
||||
@ -55,7 +55,7 @@ describe("user store tests", () => {
|
||||
expect(state.colorTheme).toBe("light");
|
||||
});
|
||||
|
||||
it("correctly resets theme to default value", async () => {
|
||||
it("correctly resets theme to default value", () => {
|
||||
state.colorTheme = "some other theme";
|
||||
resetTheme();
|
||||
expect(state.colorTheme).toBe(defaultThemeId);
|
||||
|
||||
@ -10,5 +10,5 @@ export interface AppEvent {
|
||||
name: string;
|
||||
action: string;
|
||||
destination?: string;
|
||||
params?: Record<string, any>;
|
||||
params?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ describe("app-paths", () => {
|
||||
sessionData: "/some-irrelevant-user-data", // By default this points to userData
|
||||
};
|
||||
|
||||
builder.beforeApplicationStart(({ mainDi }) => {
|
||||
await builder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.override(
|
||||
getElectronAppPathInjectable,
|
||||
() =>
|
||||
@ -120,7 +120,7 @@ describe("app-paths", () => {
|
||||
let windowDi: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
builder.beforeApplicationStart(({ mainDi }) => {
|
||||
await builder.beforeApplicationStart(({ mainDi }) => {
|
||||
mainDi.override(
|
||||
directoryForIntegrationTestingInjectable,
|
||||
() => "/some-integration-testing-app-data",
|
||||
|
||||
@ -4,6 +4,12 @@
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
|
||||
interface NonWebpackRequire {
|
||||
resolve(name: string): string;
|
||||
}
|
||||
|
||||
declare const __non_webpack_require__: NonWebpackRequire;
|
||||
|
||||
const pathToNpmCliInjectable = getInjectable({
|
||||
id: "path-to-npm-cli",
|
||||
instantiate: () => __non_webpack_require__.resolve("npm"),
|
||||
|
||||
@ -19,7 +19,7 @@ export class GeneralEntity extends CatalogEntity<CatalogEntityMetadata, CatalogE
|
||||
public readonly apiVersion = "entity.k8slens.dev/v1alpha1";
|
||||
public readonly kind = "General";
|
||||
|
||||
async onRun(context: CatalogEntityActionContext) {
|
||||
onRun(context: CatalogEntityActionContext) {
|
||||
context.navigate(this.spec.path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,8 +55,7 @@ export interface KubernetesClusterMetadata extends CatalogEntityMetadata {
|
||||
*/
|
||||
export type KubernetesClusterStatusPhase = "connected" | "connecting" | "disconnected" | "deleting";
|
||||
|
||||
export interface KubernetesClusterStatus extends CatalogEntityStatus {
|
||||
}
|
||||
export type KubernetesClusterStatus = CatalogEntityStatus;
|
||||
|
||||
export function isKubernetesCluster(item: unknown): item is KubernetesCluster {
|
||||
return item instanceof KubernetesCluster;
|
||||
@ -89,18 +88,10 @@ export class KubernetesCluster<
|
||||
await requestClusterDeactivation(this.getId());
|
||||
}
|
||||
|
||||
async onRun(context: CatalogEntityActionContext) {
|
||||
onRun(context: CatalogEntityActionContext) {
|
||||
context.navigate(`/cluster/${this.getId()}`);
|
||||
}
|
||||
|
||||
onDetailsOpen(): void {
|
||||
//
|
||||
}
|
||||
|
||||
onSettingsOpen(): void {
|
||||
//
|
||||
}
|
||||
|
||||
onContextMenuOpen(context: CatalogEntityContextMenuContext) {
|
||||
if (!this.metadata.source || this.metadata.source === "local") {
|
||||
context.menuItems.push({
|
||||
@ -120,8 +111,8 @@ export class KubernetesCluster<
|
||||
title: "Disconnect",
|
||||
icon: "link_off",
|
||||
onClick: () => {
|
||||
this.disconnect();
|
||||
broadcastMessage(
|
||||
void this.disconnect();
|
||||
void broadcastMessage(
|
||||
IpcRendererNavigationEvents.NAVIGATE_IN_APP,
|
||||
"/catalog",
|
||||
);
|
||||
|
||||
@ -26,7 +26,7 @@ export class WebLink extends CatalogEntity<CatalogEntityMetadata, WebLinkStatus,
|
||||
public readonly apiVersion = WebLink.apiVersion;
|
||||
public readonly kind = WebLink.kind;
|
||||
|
||||
async onRun() {
|
||||
onRun() {
|
||||
window.open(this.spec.url, "_blank");
|
||||
}
|
||||
|
||||
|
||||
@ -89,7 +89,7 @@ export interface CatalogCategorySpec {
|
||||
/**
|
||||
* If the filter return a thruthy value, the menu item is displayed
|
||||
*/
|
||||
export type AddMenuFilter = (menu: CatalogEntityAddMenu) => any;
|
||||
export type AddMenuFilter = (menu: CatalogEntityAddMenu) => unknown;
|
||||
|
||||
export interface CatalogCategoryEvents {
|
||||
/**
|
||||
@ -291,7 +291,7 @@ export interface CatalogEntitySettingsMenu {
|
||||
group?: string;
|
||||
title: string;
|
||||
components: {
|
||||
View: React.ComponentType<any>;
|
||||
View: React.ComponentType<Record<string, never>>;
|
||||
};
|
||||
}
|
||||
|
||||
@ -323,7 +323,7 @@ export interface CatalogEntityAddMenuContext {
|
||||
menuItems: CatalogEntityAddMenu[];
|
||||
}
|
||||
|
||||
export type CatalogEntitySpec = Record<string, any>;
|
||||
export type CatalogEntitySpec = Record<string, unknown>;
|
||||
|
||||
|
||||
export interface CatalogEntityData<
|
||||
@ -409,7 +409,17 @@ export abstract class CatalogEntity<
|
||||
return this.status.enabled ?? true;
|
||||
}
|
||||
|
||||
public onRun?(context: CatalogEntityActionContext): void | Promise<void>;
|
||||
public onContextMenuOpen?(context: CatalogEntityContextMenuContext): void | Promise<void>;
|
||||
public onSettingsOpen?(context: CatalogEntitySettingsContext): void | Promise<void>;
|
||||
public onRun(context: CatalogEntityActionContext): void | Promise<void> {
|
||||
void context;
|
||||
}
|
||||
public onContextMenuOpen(context: CatalogEntityContextMenuContext): void | Promise<void> {
|
||||
void context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This has never been used
|
||||
*/
|
||||
public onSettingsOpen(context: CatalogEntitySettingsContext): void | Promise<void> {
|
||||
void context;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,13 +3,13 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { action, computed, observable, makeObservable } from "mobx";
|
||||
import { action, computed, observable, makeObservable, runInAction } from "mobx";
|
||||
import { once } from "lodash";
|
||||
import { iter, getOrInsertMap, strictSet } from "@k8slens/utilities";
|
||||
import type { Disposer } from "@k8slens/utilities";
|
||||
import type { CatalogCategory, CatalogEntityData, CatalogEntityKindData } from "./catalog-entity";
|
||||
|
||||
export type CategoryFilter = (category: CatalogCategory) => any;
|
||||
export type CategoryFilter = (category: CatalogCategory) => unknown;
|
||||
|
||||
export class CatalogCategoryRegistry {
|
||||
protected readonly categories = observable.set<CatalogCategory>();
|
||||
@ -22,16 +22,18 @@ export class CatalogCategoryRegistry {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
@action add(category: CatalogCategory): Disposer {
|
||||
const byGroup = getOrInsertMap(this.groupKinds, category.spec.group);
|
||||
add(category: CatalogCategory): Disposer {
|
||||
return runInAction(() => {
|
||||
const byGroup = getOrInsertMap(this.groupKinds, category.spec.group);
|
||||
|
||||
this.categories.add(category);
|
||||
strictSet(byGroup, category.spec.names.kind, category);
|
||||
this.categories.add(category);
|
||||
strictSet(byGroup, category.spec.names.kind, category);
|
||||
|
||||
return () => {
|
||||
this.categories.delete(category);
|
||||
byGroup.delete(category.spec.names.kind);
|
||||
};
|
||||
return action(() => {
|
||||
this.categories.delete(category);
|
||||
byGroup.delete(category.spec.names.kind);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getById(id: string) {
|
||||
|
||||
@ -54,7 +54,7 @@ export function getShortName(entity: CatalogEntity): string {
|
||||
}
|
||||
|
||||
export function getIconColourHash(entity: CatalogEntity): string {
|
||||
return `${entity.metadata.name}-${entity.metadata.source}`;
|
||||
return `${entity.metadata.name}-${entity.metadata.source ?? ""}`;
|
||||
}
|
||||
|
||||
export function getIconBackground(entity: CatalogEntity): string | undefined {
|
||||
|
||||
@ -14,7 +14,7 @@ const visitEntityContextMenuInjectable = getInjectable({
|
||||
const categoryRegistry = di.inject(catalogCategoryRegistryInjectable);
|
||||
|
||||
return (entity, context) => {
|
||||
entity.onContextMenuOpen?.(context);
|
||||
void entity.onContextMenuOpen(context);
|
||||
categoryRegistry.getCategoryForEntity(entity)?.emit("contextMenuOpen", entity, context);
|
||||
};
|
||||
},
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import Joi from "joi";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
* JSON serializable metadata type
|
||||
*/
|
||||
export type ClusterMetadata = Record<string, string | number | boolean | object>;
|
||||
export type ClusterMetadata = Partial<Record<string, Metadata>>;
|
||||
|
||||
/**
|
||||
* Metadata for cluster's prometheus settings
|
||||
@ -29,31 +29,55 @@ export type ClusterId = string;
|
||||
*/
|
||||
export type UpdateClusterModel = Omit<ClusterModel, "id">;
|
||||
|
||||
export type Literal = z.infer<typeof literalSchema>;
|
||||
export const literalSchema = z.string().or(z.number()).or(z.boolean());
|
||||
|
||||
export type Metadata = Literal | { [key: string]: Metadata } | Metadata[];
|
||||
export const metadataSchema: z.ZodType<Metadata> = z.lazy(() => z.union([literalSchema, z.array(metadataSchema), z.record(metadataSchema)]));
|
||||
|
||||
export const prometheusPreferencesSchema = z.object({
|
||||
namespace: z.string(),
|
||||
service: z.string(),
|
||||
prefix: z.string(),
|
||||
port: z.number(),
|
||||
});
|
||||
|
||||
export const prometheusProviderPreferencesSchema = z.object({
|
||||
type: z.string(),
|
||||
});
|
||||
|
||||
export const preferencesSchema = z.object({
|
||||
terminalCWD: z.string().min(1).optional(),
|
||||
clusterName: z.string().min(1).optional(),
|
||||
httpsProxy: z.string().min(1).optional(),
|
||||
nodeShellImage: z.string().min(1).optional(),
|
||||
imagePullSecret: z.string().min(1).optional(),
|
||||
defaultNamespace: z.string().min(1).optional(),
|
||||
iconOrder: z.number().optional(),
|
||||
icon: z.nullable(z.string()).optional(),
|
||||
hiddenMetrics: z.array(z.string()).optional(),
|
||||
prometheus: prometheusPreferencesSchema.optional(),
|
||||
prometheusProvider: prometheusProviderPreferencesSchema.optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* A type validator for `UpdateClusterModel` so that only expected types are present
|
||||
*/
|
||||
export const updateClusterModelChecker = Joi.object<UpdateClusterModel>({
|
||||
kubeConfigPath: Joi.string()
|
||||
.required()
|
||||
.min(1),
|
||||
contextName: Joi.string()
|
||||
.required()
|
||||
.min(1),
|
||||
preferences: Joi.object(),
|
||||
metadata: Joi.object(),
|
||||
accessibleNamespaces: Joi.array()
|
||||
.items(Joi.string()),
|
||||
labels: Joi.object().pattern(Joi.string(), Joi.string()),
|
||||
export const updateClusterModelSchema = z.object({
|
||||
kubeConfigPath: z.string().min(1),
|
||||
contextName: z.string().min(1),
|
||||
preferences: preferencesSchema.optional(),
|
||||
metadata: z.record(metadataSchema).optional(),
|
||||
accessibleNamespaces: z.array(z.string()).optional(),
|
||||
labels: z.record(z.string()).optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* A type validator for just the `id` fields of `ClusterModel`. The rest is
|
||||
* covered by `updateClusterModelChecker`
|
||||
*/
|
||||
export const clusterModelIdChecker = Joi.object<Pick<ClusterModel, "id">>({
|
||||
id: Joi.string()
|
||||
.required()
|
||||
.min(1),
|
||||
export const clusterModelIdSchema = z.object({
|
||||
id: z.string().min(1),
|
||||
});
|
||||
|
||||
/**
|
||||
@ -85,7 +109,7 @@ export interface ClusterModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* This data is retreived from the kubeconfig file before calling the cluster constructor.
|
||||
* This data is retrieved from the kubeconfig file before calling the cluster constructor.
|
||||
*
|
||||
* That is done to remove the external dependency on the construction of Cluster instances.
|
||||
*/
|
||||
|
||||
@ -6,10 +6,12 @@
|
||||
import { computed, observable, toJS, runInAction } from "mobx";
|
||||
import type { KubeApiResource } from "../rbac";
|
||||
import type { ClusterState, ClusterId, ClusterMetadata, ClusterModel, ClusterPreferences, ClusterPrometheusPreferences, UpdateClusterModel } from "../cluster-types";
|
||||
import { ClusterMetadataKey, clusterModelIdChecker, updateClusterModelChecker } from "../cluster-types";
|
||||
import { ClusterMetadataKey, clusterModelIdSchema, updateClusterModelSchema } from "../cluster-types";
|
||||
import type { IObservableValue } from "mobx";
|
||||
import { replaceObservableObject } from "../utils/replace-observable-object";
|
||||
import { pick } from "lodash";
|
||||
import type { ZodError } from "zod";
|
||||
import type { Result } from "@k8slens/utilities";
|
||||
|
||||
export class Cluster {
|
||||
/**
|
||||
@ -20,12 +22,12 @@ export class Cluster {
|
||||
/**
|
||||
* Kubeconfig context name
|
||||
*/
|
||||
readonly contextName = observable.box() as IObservableValue<string>;
|
||||
readonly contextName: IObservableValue<string>;
|
||||
|
||||
/**
|
||||
* Path to kubeconfig
|
||||
*/
|
||||
readonly kubeConfigPath = observable.box() as IObservableValue<string>;
|
||||
readonly kubeConfigPath: IObservableValue<string>;
|
||||
|
||||
/**
|
||||
* Describes if we can detect that cluster is online
|
||||
@ -117,15 +119,58 @@ export class Cluster {
|
||||
*/
|
||||
readonly prometheusPreferences = computed(() => pick(toJS(this.preferences), "prometheus", "prometheusProvider") as ClusterPrometheusPreferences);
|
||||
|
||||
constructor({ id, ...model }: ClusterModel) {
|
||||
const { error } = clusterModelIdChecker.validate({ id });
|
||||
static create({ id, ...model }: ClusterModel): Result<Cluster, ZodError<unknown>> {
|
||||
const clusterIdResult = clusterModelIdSchema.safeParse({ id });
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
if (!clusterIdResult.success) {
|
||||
return {
|
||||
isOk: false,
|
||||
error: clusterIdResult.error,
|
||||
};
|
||||
}
|
||||
|
||||
const updateModelResult = updateClusterModelSchema.safeParse(model);
|
||||
|
||||
if (!updateModelResult.success) {
|
||||
return {
|
||||
isOk: false,
|
||||
error: updateModelResult.error,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
isOk: true,
|
||||
value: new Cluster(clusterIdResult.data.id, updateModelResult.data),
|
||||
};
|
||||
}
|
||||
|
||||
static createForTestingOnly({ id, ...model }: ClusterModel): Cluster {
|
||||
const clusterIdResult = clusterModelIdSchema.parse({ id });
|
||||
const updateModelResult = updateClusterModelSchema.parse(model);
|
||||
|
||||
return new Cluster(clusterIdResult.id, updateModelResult);
|
||||
}
|
||||
|
||||
private constructor(id: string, model: UpdateClusterModel) {
|
||||
this.id = id;
|
||||
this.updateModel(model);
|
||||
this.kubeConfigPath = observable.box(model.kubeConfigPath);
|
||||
this.contextName = observable.box(model.contextName);
|
||||
|
||||
if (model.preferences) {
|
||||
replaceObservableObject(this.preferences, model.preferences);
|
||||
}
|
||||
|
||||
if (model.metadata) {
|
||||
replaceObservableObject(this.metadata, model.metadata);
|
||||
}
|
||||
|
||||
if (model.accessibleNamespaces) {
|
||||
this.accessibleNamespaces.replace(model.accessibleNamespaces);
|
||||
}
|
||||
|
||||
if (model.labels) {
|
||||
replaceObservableObject(this.labels, model.labels);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,13 +178,14 @@ export class Cluster {
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
updateModel(model: UpdateClusterModel) {
|
||||
// Note: do not assign ID as that should never be updated
|
||||
updateModel(model: UpdateClusterModel): Result<Cluster, ZodError<unknown>> {
|
||||
const updateModelResult = updateClusterModelSchema.safeParse(model);
|
||||
|
||||
const { error } = updateClusterModelChecker.validate(model, { allowUnknown: true });
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
if (!updateModelResult.success) {
|
||||
return {
|
||||
isOk: false,
|
||||
error: updateModelResult.error,
|
||||
};
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
@ -162,6 +208,11 @@ export class Cluster {
|
||||
replaceObservableObject(this.labels, model.labels);
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
isOk: true,
|
||||
value: this,
|
||||
};
|
||||
}
|
||||
|
||||
toJSON(): ClusterModel {
|
||||
|
||||
@ -31,7 +31,7 @@ const createCanIInjectable = getInjectable({
|
||||
|
||||
return body.status?.allowed ?? false;
|
||||
} catch (error) {
|
||||
logger.error(`[AUTHORIZATION-REVIEW]: failed to create access review: ${error}`, { resourceAttributes });
|
||||
logger.error(`[AUTHORIZATION-REVIEW]: failed to create access review: ${String(error)}`, { resourceAttributes });
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ const createRequestNamespaceListPermissionsInjectable = getInjectable({
|
||||
});
|
||||
|
||||
if (!status || status.incomplete) {
|
||||
logger.warn(`[AUTHORIZATION-NAMESPACE-REVIEW]: allowing all resources in namespace="${namespace}" due to incomplete SelfSubjectRulesReview: ${status?.evaluationError}`);
|
||||
logger.warn(`[AUTHORIZATION-NAMESPACE-REVIEW]: allowing all resources in namespace="${namespace}" due to incomplete SelfSubjectRulesReview: ${status?.evaluationError ?? ""}`);
|
||||
|
||||
return () => true;
|
||||
}
|
||||
|
||||
@ -6,27 +6,17 @@ import type { KubeConfig } from "@kubernetes/client-node";
|
||||
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
|
||||
import type { Cluster } from "./cluster";
|
||||
import loadConfigFromFileInjectable from "../kube-helpers/load-config-from-file.injectable";
|
||||
import type { ConfigResult } from "../kube-helpers";
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import type { ZodError } from "zod";
|
||||
|
||||
export interface LoadKubeconfig {
|
||||
(fullResult?: false): Promise<KubeConfig>;
|
||||
(fullResult: true): Promise<ConfigResult>;
|
||||
}
|
||||
export type LoadKubeconfig = () => AsyncResult<KubeConfig, ZodError<unknown>>;
|
||||
|
||||
const loadKubeconfigInjectable = getInjectable({
|
||||
id: "load-kubeconfig",
|
||||
instantiate: (di, cluster) => {
|
||||
const loadConfigFromFile = di.inject(loadConfigFromFileInjectable);
|
||||
|
||||
return (async (fullResult = false) => {
|
||||
const result = await loadConfigFromFile(cluster.kubeConfigPath.get());
|
||||
|
||||
if (fullResult) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return result.config;
|
||||
}) as LoadKubeconfig;
|
||||
return () => loadConfigFromFile(cluster.kubeConfigPath.get());
|
||||
},
|
||||
lifecycle: lifecycleEnum.keyedSingleton({
|
||||
getInstanceKey: (di, cluster: Cluster) => cluster.id,
|
||||
|
||||
@ -193,7 +193,7 @@ describe("requestNamespaceListPermissions", () => {
|
||||
status,
|
||||
spec: {},
|
||||
},
|
||||
response: null as unknown as IncomingMessage,
|
||||
value: null as unknown as IncomingMessage,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -25,26 +25,26 @@ const downloadBinaryInjectable = getInjectable({
|
||||
result = await fetch(url, opts as RequestInit);
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
isOk: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
|
||||
if (result.status < 200 || 300 <= result.status) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
isOk: false,
|
||||
error: result.statusText,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
response: await result.buffer(),
|
||||
isOk: true,
|
||||
value: await result.buffer(),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
isOk: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
|
||||
@ -19,26 +19,26 @@ export const downloadJsonWith = (fetch: Fetch): DownloadJson => async (url, opts
|
||||
result = await fetch(url, opts as RequestInit);
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
isOk: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
|
||||
if (result.status < 200 || 300 <= result.status) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
isOk: false,
|
||||
error: result.statusText,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
response: await result.json(),
|
||||
isOk: true,
|
||||
value: await result.json(),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
isOk: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
|
||||
@ -18,9 +18,11 @@ type RequiredKeys<T> = Exclude<
|
||||
|
||||
type ObjectContainingNoRequired<T> = T extends void
|
||||
? never
|
||||
: RequiredKeys<T> extends []
|
||||
? any
|
||||
: never;
|
||||
: (
|
||||
RequiredKeys<T> extends []
|
||||
? Record<string, never>
|
||||
: never
|
||||
);
|
||||
|
||||
type ObjectContainsNoRequired<T> = T extends ObjectContainingNoRequired<T>
|
||||
? true
|
||||
@ -30,10 +32,12 @@ type ObjectContainsNoRequired<T> = T extends ObjectContainingNoRequired<T>
|
||||
// - Navigating to route without parameters, with parameters
|
||||
// - Navigating to route with required parameters, without parameters
|
||||
type Parameters<TParameters> = TParameters extends void
|
||||
? {}
|
||||
: ObjectContainsNoRequired<TParameters> extends true
|
||||
? { parameters?: TParameters }
|
||||
: { parameters: TParameters };
|
||||
? { parameters?: undefined }
|
||||
: (
|
||||
ObjectContainsNoRequired<TParameters> extends true
|
||||
? { parameters?: TParameters }
|
||||
: { parameters: TParameters }
|
||||
);
|
||||
|
||||
export type NavigateToRouteOptions<TRoute> = Parameters<
|
||||
InferParametersFrom<TRoute>
|
||||
|
||||
@ -9,7 +9,7 @@ export interface NavigateToUrlOptions {
|
||||
forceRootFrame?: boolean;
|
||||
}
|
||||
|
||||
export type NavigateToUrl = (url: string, options?: NavigateToUrlOptions) => void;
|
||||
export type NavigateToUrl = (url: string, options?: NavigateToUrlOptions) => void | Promise<void>;
|
||||
|
||||
export const navigateToUrlInjectionToken = getInjectionToken<NavigateToUrl>(
|
||||
{ id: "navigate-to-url-injection-token" },
|
||||
|
||||
@ -6,6 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ExecFileException, ExecFileOptions } from "child_process";
|
||||
import { execFile } from "child_process";
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import { isArray } from "@k8slens/utilities";
|
||||
|
||||
export type ExecFileError = ExecFileException & { stderr: string };
|
||||
|
||||
@ -21,7 +22,7 @@ const execFileInjectable = getInjectable({
|
||||
instantiate: (): ExecFile => {
|
||||
return (filePath: string, argsOrOptions?: string[] | ExecFileOptions, maybeOptions?: ExecFileOptions) => {
|
||||
const { args, options } = (() => {
|
||||
if (Array.isArray(argsOrOptions)) {
|
||||
if (isArray(argsOrOptions)) {
|
||||
return {
|
||||
args: argsOrOptions,
|
||||
options: maybeOptions ?? {},
|
||||
@ -38,13 +39,13 @@ const execFileInjectable = getInjectable({
|
||||
execFile(filePath, args, options, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
resolve({
|
||||
callWasSuccessful: false,
|
||||
isOk: false,
|
||||
error: Object.assign(error, { stderr }),
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
callWasSuccessful: true,
|
||||
response: stdout,
|
||||
isOk: true,
|
||||
value: stdout,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
import { getGlobalOverride } from "@k8slens/test-utils";
|
||||
import extractTarInjectable from "./extract-tar.injectable";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
export default getGlobalOverride(extractTarInjectable, () => async () => {
|
||||
throw new Error("tried to extract a tar file without override");
|
||||
});
|
||||
|
||||
@ -3,9 +3,12 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { WriteFileOptions } from "fs";
|
||||
import type { ReadOptions } from "fs-extra";
|
||||
import fse from "fs-extra";
|
||||
|
||||
export type FileSystemFunctions = ReturnType<(typeof fsInjectable)["instantiate"]>;
|
||||
|
||||
/**
|
||||
* NOTE: Add corresponding override of this injectable in `src/test-utils/override-fs-with-fakes.ts`
|
||||
*/
|
||||
@ -40,13 +43,13 @@ const fsInjectable = getInjectable({
|
||||
|
||||
return {
|
||||
readFile,
|
||||
readJson: readJson as (file: string, options?: ReadOptions | BufferEncoding) => Promise<any>,
|
||||
readJson: readJson as (file: string, options?: ReadOptions | BufferEncoding) => Promise<unknown>,
|
||||
writeFile,
|
||||
writeJson,
|
||||
writeJson: writeJson as (file: string, value: unknown, options?: string | WriteFileOptions) => Promise<void>,
|
||||
pathExists,
|
||||
readdir,
|
||||
readFileSync,
|
||||
readJsonSync,
|
||||
readJsonSync: readJsonSync as (file: string, options?: ReadOptions | BufferEncoding) => unknown,
|
||||
writeFileSync,
|
||||
writeJsonSync,
|
||||
pathExistsSync,
|
||||
|
||||
@ -3,10 +3,9 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { JsonValue } from "type-fest";
|
||||
import fsInjectable from "./fs.injectable";
|
||||
|
||||
export type ReadJson = (filePath: string) => Promise<JsonValue>;
|
||||
export type ReadJson = (filePath: string) => Promise<unknown>;
|
||||
|
||||
const readJsonFileInjectable = getInjectable({
|
||||
id: "read-json-file",
|
||||
|
||||
@ -9,7 +9,7 @@ import type { Stats } from "fs-extra";
|
||||
import { lowerFirst } from "lodash/fp";
|
||||
import statInjectable from "./stat.injectable";
|
||||
|
||||
export type ValidateDirectory = (path: string) => AsyncResult<undefined>;
|
||||
export type ValidateDirectory = (path: string) => AsyncResult<undefined, string>;
|
||||
|
||||
function getUserReadableFileType(stats: Stats): string {
|
||||
if (stats.isFile()) {
|
||||
@ -46,13 +46,13 @@ const validateDirectoryInjectable = getInjectable({
|
||||
const stats = await stat(path);
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
return { callWasSuccessful: true, response: undefined };
|
||||
return { isOk: true, value: undefined };
|
||||
}
|
||||
|
||||
return { callWasSuccessful: false, error: `the provided path is ${getUserReadableFileType(stats)} and not a directory.` };
|
||||
return { isOk: false, error: `the provided path is ${getUserReadableFileType(stats)} and not a directory.` };
|
||||
} catch (error) {
|
||||
if (!isErrnoException(error)) {
|
||||
return { callWasSuccessful: false, error: "of an unknown error, please try again." };
|
||||
return { isOk: false, error: "of an unknown error, please try again." };
|
||||
}
|
||||
|
||||
const humanReadableErrors: Record<string, string> = {
|
||||
@ -67,7 +67,7 @@ const validateDirectoryInjectable = getInjectable({
|
||||
? humanReadableErrors[error.code]
|
||||
: lowerFirst(String(error));
|
||||
|
||||
return { callWasSuccessful: false, error: humanReadableError };
|
||||
return { isOk: false, error: humanReadableError };
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
@ -12,6 +12,7 @@ import readJsonSyncInjectable from "../fs/read-json-sync.injectable";
|
||||
import writeJsonSyncInjectable from "../fs/write-json-sync.injectable";
|
||||
import { get, has, set } from "lodash";
|
||||
import semver from "semver";
|
||||
import type { Options as ConfOptions } from "conf/dist/source/types";
|
||||
|
||||
const MIGRATION_KEY = `__internal__.migrations.version`;
|
||||
|
||||
@ -43,16 +44,16 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
|
||||
const readJsonSync = di.inject(readJsonSyncInjectable);
|
||||
const writeJsonSync = di.inject(writeJsonSyncInjectable);
|
||||
|
||||
return (options) => {
|
||||
return <T extends object>(options: ConfOptions<T>) => {
|
||||
assert(options.cwd, "Missing options.cwd");
|
||||
assert(options.configName, "Missing options.configName");
|
||||
assert(options.projectVersion, "Missing options.projectVersion");
|
||||
|
||||
const configFilePath = path.posix.join(options.cwd, `${options.configName}.json`);
|
||||
let store: object = {};
|
||||
let store: Partial<Record<string, unknown>> = {};
|
||||
|
||||
try {
|
||||
store = readJsonSync(configFilePath);
|
||||
store = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
@ -62,12 +63,12 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
|
||||
return store;
|
||||
},
|
||||
path: configFilePath,
|
||||
get: (key: string) => get(store, key),
|
||||
get: (key: string) => get(store, key) as unknown,
|
||||
set: (key: string, value: unknown) => {
|
||||
let currentState: Partial<Record<string, unknown>>;
|
||||
|
||||
try {
|
||||
currentState = readJsonSync(configFilePath);
|
||||
currentState = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
|
||||
} catch {
|
||||
currentState = {};
|
||||
}
|
||||
@ -76,13 +77,13 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
|
||||
...currentState,
|
||||
[key]: value,
|
||||
});
|
||||
store = readJsonSync(configFilePath);
|
||||
store = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
|
||||
},
|
||||
delete: (key: string) => {
|
||||
let currentState: Partial<Record<string, unknown>>;
|
||||
|
||||
try {
|
||||
currentState = readJsonSync(configFilePath);
|
||||
currentState = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
|
||||
} catch {
|
||||
currentState = {};
|
||||
}
|
||||
@ -90,20 +91,20 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
|
||||
delete currentState[key];
|
||||
|
||||
writeJsonSync(configFilePath, currentState);
|
||||
store = readJsonSync(configFilePath);
|
||||
store = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
|
||||
},
|
||||
has: (key: string) => has(store, key),
|
||||
clear: () => {
|
||||
writeJsonSync(configFilePath, {});
|
||||
store = readJsonSync(configFilePath);
|
||||
store = readJsonSync(configFilePath) as Partial<Record<string, unknown>>;
|
||||
},
|
||||
} as Partial<Config> as Config<any>;
|
||||
} as Partial<Config> as Config<T>;
|
||||
|
||||
// Migrate
|
||||
{
|
||||
const migrations = options.migrations ?? [];
|
||||
const versionToMigrate = options.projectVersion;
|
||||
let previousMigratedVersion = get(store, MIGRATION_KEY) || "0.0.0";
|
||||
let previousMigratedVersion = String(get(store, MIGRATION_KEY)) || "0.0.0";
|
||||
const newerVersions = Object.entries(migrations)
|
||||
.filter(([candidateVersion]) => _shouldPerformMigration(candidateVersion, previousMigratedVersion, versionToMigrate));
|
||||
|
||||
@ -118,7 +119,7 @@ export default getGlobalOverride(getConfigurationFileModelInjectable, (di) => {
|
||||
}
|
||||
catch (error) {
|
||||
store = storeBackup;
|
||||
throw new Error(`Something went wrong during the migration! Changes applied to the store until this failed migration will be restored. ${error}`);
|
||||
throw new Error(`Something went wrong during the migration! Changes applied to the store until this failed migration will be restored. ${String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,5 +8,5 @@ import { getRequestChannel } from "@k8slens/messaging";
|
||||
|
||||
export const getActiveHelmRepositoriesChannel = getRequestChannel<
|
||||
void,
|
||||
AsyncResult<HelmRepo[]>
|
||||
AsyncResult<HelmRepo[], string>
|
||||
>("get-helm-active-list-repositories");
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import type { Runnable } from "@k8slens/run-many";
|
||||
import { isArray } from "@k8slens/utilities";
|
||||
import type { DiContainerForInjection, Injectable, InjectionToken } from "@ogre-tools/injectable";
|
||||
import { getInjectionToken, getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
@ -67,7 +68,7 @@ export const getInjectablesForInitializable = <T>({
|
||||
runAfter: rest.runAfter,
|
||||
}),
|
||||
injectionToken: (() => {
|
||||
if (rest.runAfter && !Array.isArray(rest.runAfter)) {
|
||||
if (rest.runAfter && !isArray(rest.runAfter)) {
|
||||
return rest.runAfter.injectionToken;
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { broadcastMessage } from "./ipc";
|
||||
|
||||
export type BroadcastMessage = (channel: string, ...args: any[]) => Promise<void>;
|
||||
export type BroadcastMessage = (channel: string, ...args: unknown[]) => Promise<void>;
|
||||
|
||||
const broadcastMessageInjectable = getInjectable({
|
||||
id: "broadcast-message",
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
import { ipcMain, ipcRenderer, webContents } from "electron";
|
||||
import { toJS } from "../utils/toJS";
|
||||
import type { Disposer } from "@k8slens/utilities";
|
||||
import { isArray } from "@k8slens/utilities";
|
||||
import { getLegacyGlobalDiForExtensionApi } from "@k8slens/legacy-global-di";
|
||||
import ipcRendererInjectable from "../../renderer/utils/channel/ipc-renderer.injectable";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
@ -18,19 +19,21 @@ import clusterFramesInjectable from "../cluster-frames.injectable";
|
||||
|
||||
export const broadcastMainChannel = "ipc:broadcast-main";
|
||||
|
||||
export function ipcMainHandle(channel: string, listener: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any) {
|
||||
export function ipcMainHandle(channel: string, listener: (event: Electron.IpcMainInvokeEvent, ...args: unknown[]) => unknown) {
|
||||
const di = getLegacyGlobalDiForExtensionApi();
|
||||
|
||||
const ipcMain = di.inject(ipcMainInjectionToken);
|
||||
|
||||
ipcMain.handle(channel, async (event, ...args) => {
|
||||
return sanitizePayload(await listener(event, ...args));
|
||||
ipcMain.handle(channel, async (event, ...args: unknown[]) => {
|
||||
return toJS(await listener(event, ...args));
|
||||
});
|
||||
}
|
||||
|
||||
export async function broadcastMessage(channel: string, ...args: any[]): Promise<void> {
|
||||
export async function broadcastMessage(channel: string, ...args: unknown[]): Promise<void> {
|
||||
if (ipcRenderer) {
|
||||
return ipcRenderer.invoke(broadcastMainChannel, channel, ...args.map(sanitizePayload));
|
||||
await ipcRenderer.invoke(broadcastMainChannel, channel, ...args.map(toJS));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!webContents) {
|
||||
@ -41,15 +44,23 @@ export async function broadcastMessage(channel: string, ...args: any[]): Promise
|
||||
const logger = di.inject(loggerInjectionToken);
|
||||
const clusterFrames = di.inject(clusterFramesInjectable);
|
||||
|
||||
ipcMain.listeners(channel).forEach((func) => func({
|
||||
processId: undefined, frameId: undefined, sender: undefined, senderFrame: undefined,
|
||||
}, ...args));
|
||||
ipcMain.listeners(channel).forEach((func) => {
|
||||
func(
|
||||
{
|
||||
processId: undefined,
|
||||
frameId: undefined,
|
||||
sender: undefined,
|
||||
senderFrame: undefined,
|
||||
},
|
||||
...args,
|
||||
);
|
||||
});
|
||||
|
||||
const views = webContents.getAllWebContents();
|
||||
|
||||
if (!views || !Array.isArray(views) || views.length === 0) return;
|
||||
if (!views || !isArray(views) || views.length === 0) return;
|
||||
|
||||
args = args.map(sanitizePayload);
|
||||
args = args.map(toJS);
|
||||
|
||||
for (const view of views) {
|
||||
let viewType = "unknown";
|
||||
@ -82,7 +93,7 @@ export async function broadcastMessage(channel: string, ...args: any[]): Promise
|
||||
}
|
||||
}
|
||||
|
||||
export function ipcMainOn(channel: string, listener: (event: Electron.IpcMainEvent, ...args: any[]) => any): Disposer {
|
||||
export function ipcMainOn(channel: string, listener: (event: Electron.IpcMainEvent, ...args: unknown[]) => unknown): Disposer {
|
||||
const di = getLegacyGlobalDiForExtensionApi();
|
||||
|
||||
const ipcMain = di.inject(ipcMainInjectionToken);
|
||||
@ -92,7 +103,7 @@ export function ipcMainOn(channel: string, listener: (event: Electron.IpcMainEve
|
||||
return () => ipcMain.off(channel, listener);
|
||||
}
|
||||
|
||||
export function ipcRendererOn(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
|
||||
export function ipcRendererOn(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: unknown[]) => unknown): Disposer {
|
||||
const di = getLegacyGlobalDiForExtensionApi();
|
||||
|
||||
const ipcRenderer = di.inject(ipcRendererInjectable);
|
||||
@ -101,11 +112,3 @@ export function ipcRendererOn(channel: string, listener: (event: Electron.IpcRen
|
||||
|
||||
return () => ipcRenderer.off(channel, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizing data for IPC-messaging before send.
|
||||
* Removes possible observable values to avoid exceptions like "can't clone object".
|
||||
*/
|
||||
function sanitizePayload<T>(data: any): T {
|
||||
return toJS(data);
|
||||
}
|
||||
|
||||
@ -57,11 +57,11 @@ export abstract class ItemStore<Item extends ItemObject> {
|
||||
* @param order whether to sort from least to greatest (`"asc"` (default)) or vice-versa (`"desc"`)
|
||||
*/
|
||||
@action
|
||||
protected sortItems(items: Item[] = this.items, sorting: ((item: Item) => any)[] = [this.defaultSorting], order?: "asc" | "desc"): Item[] {
|
||||
protected sortItems(items: Item[] = this.items, sorting: ((item: Item) => unknown)[] = [this.defaultSorting], order?: "asc" | "desc"): Item[] {
|
||||
return orderBy(items, sorting, order);
|
||||
}
|
||||
|
||||
protected async createItem(...args: any[]): Promise<any>;
|
||||
protected async createItem(...args: unknown[]): Promise<unknown>;
|
||||
@action
|
||||
protected async createItem(request: () => Promise<Item>) {
|
||||
const newItem = await request();
|
||||
@ -78,7 +78,7 @@ export abstract class ItemStore<Item extends ItemObject> {
|
||||
}
|
||||
}
|
||||
|
||||
protected async loadItems(...args: any[]): Promise<any>;
|
||||
protected async loadItems(...args: unknown[]): Promise<unknown>;
|
||||
/**
|
||||
* Load items to this.items
|
||||
* @param request Function to return the items to be loaded.
|
||||
@ -87,7 +87,7 @@ export abstract class ItemStore<Item extends ItemObject> {
|
||||
* @returns
|
||||
*/
|
||||
@action
|
||||
protected async loadItems(request: () => Promise<Item[] | any>, sortItems = true, concurrency = false) {
|
||||
protected async loadItems(request: () => Promise<Item[]>, sortItems = true, concurrency = false) {
|
||||
if (this.isLoading) {
|
||||
await when(() => !this.isLoading);
|
||||
|
||||
@ -142,7 +142,7 @@ export abstract class ItemStore<Item extends ItemObject> {
|
||||
}
|
||||
|
||||
@action
|
||||
protected async removeItem(item: Item, request: () => Promise<any>) {
|
||||
protected async removeItem(item: Item, request: () => Promise<unknown>) {
|
||||
await request();
|
||||
this.items.remove(item);
|
||||
this.selectedItemsIds.delete(item.getId());
|
||||
@ -173,19 +173,19 @@ export abstract class ItemStore<Item extends ItemObject> {
|
||||
|
||||
@action
|
||||
toggleSelectionAll(visibleItems: Item[] = this.items) {
|
||||
const allSelected = visibleItems.every(this.isSelected);
|
||||
const allSelected = visibleItems.every(item => this.isSelected(item));
|
||||
|
||||
if (allSelected) {
|
||||
visibleItems.forEach(this.unselect);
|
||||
} else {
|
||||
visibleItems.forEach(this.select);
|
||||
}
|
||||
visibleItems.forEach((
|
||||
allSelected
|
||||
? (item) => this.unselect(item)
|
||||
: (item) => this.select(item)
|
||||
));
|
||||
}
|
||||
|
||||
isSelectedAll(visibleItems: Item[] = this.items) {
|
||||
if (!visibleItems.length) return false;
|
||||
|
||||
return visibleItems.every(this.isSelected);
|
||||
return visibleItems.every((item) => this.isSelected(item));
|
||||
}
|
||||
|
||||
@action
|
||||
@ -202,7 +202,7 @@ export abstract class ItemStore<Item extends ItemObject> {
|
||||
this.isLoading = false;
|
||||
}
|
||||
|
||||
async removeSelectedItems?(): Promise<any>;
|
||||
async removeSelectedItems?(): Promise<unknown>;
|
||||
|
||||
async removeItems?(items: Item[]): Promise<void>;
|
||||
|
||||
|
||||
@ -47,7 +47,7 @@ describe("ApiManager", () => {
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
di.override(hostedClusterInjectable, () => new Cluster({
|
||||
di.override(hostedClusterInjectable, () => Cluster.createForTestingOnly({
|
||||
contextName: "some-context-name",
|
||||
id: "some-cluster-id",
|
||||
kubeConfigPath: "/some-path-to-a-kubeconfig",
|
||||
|
||||
@ -12,7 +12,6 @@ import fetchInjectable from "../../fetch/fetch.injectable";
|
||||
import type { AsyncFnMock } from "@async-fn/jest";
|
||||
import asyncFn from "@async-fn/jest";
|
||||
import { flushPromises } from "@k8slens/test-utils";
|
||||
import setupAutoRegistrationInjectable from "../../../renderer/before-frame-starts/runnables/setup-auto-registration.injectable";
|
||||
import { createMockResponseFromString } from "../../../test-utils/mock-responses";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../../renderer/stores-apis-can-be-created.injectable";
|
||||
import directoryForUserDataInjectable from "../../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
@ -30,7 +29,7 @@ describe("KubeApi", () => {
|
||||
let apiManager: ApiManager;
|
||||
let di: DiContainer;
|
||||
|
||||
beforeEach(async () => {
|
||||
beforeEach(() => {
|
||||
di = getDiForUnitTesting();
|
||||
|
||||
fetchMock = asyncFn();
|
||||
@ -40,17 +39,13 @@ describe("KubeApi", () => {
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
di.override(hostedClusterInjectable, () => new Cluster({
|
||||
di.override(hostedClusterInjectable, () => Cluster.createForTestingOnly({
|
||||
contextName: "some-context-name",
|
||||
id: "some-cluster-id",
|
||||
kubeConfigPath: "/some-path-to-a-kubeconfig",
|
||||
}));
|
||||
|
||||
apiManager = di.inject(apiManagerInjectable);
|
||||
|
||||
const setupAutoRegistration = di.inject(setupAutoRegistrationInjectable);
|
||||
|
||||
setupAutoRegistration.run();
|
||||
});
|
||||
|
||||
describe("on first call to IngressApi.get()", () => {
|
||||
@ -722,7 +717,7 @@ describe("KubeApi", () => {
|
||||
],
|
||||
},
|
||||
});
|
||||
horizontalPodAutoscalerApi.get({
|
||||
void horizontalPodAutoscalerApi.get({
|
||||
name: "foo",
|
||||
namespace: "default",
|
||||
});
|
||||
|
||||
@ -14,7 +14,6 @@ import asyncFn from "@async-fn/jest";
|
||||
import { flushPromises } from "@k8slens/test-utils";
|
||||
import createKubeJsonApiInjectable from "../create-kube-json-api.injectable";
|
||||
import type { KubeStatusData } from "@k8slens/kube-object";
|
||||
import setupAutoRegistrationInjectable from "../../../renderer/before-frame-starts/runnables/setup-auto-registration.injectable";
|
||||
import { createMockResponseFromString } from "../../../test-utils/mock-responses";
|
||||
import storesAndApisCanBeCreatedInjectable from "../../../renderer/stores-apis-can-be-created.injectable";
|
||||
import directoryForUserDataInjectable from "../../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
@ -40,7 +39,7 @@ describe("createKubeApiForRemoteCluster", () => {
|
||||
di.override(directoryForKubeConfigsInjectable, () => "/some-kube-configs");
|
||||
di.override(storesAndApisCanBeCreatedInjectable, () => true);
|
||||
|
||||
di.override(hostedClusterInjectable, () => new Cluster({
|
||||
di.override(hostedClusterInjectable, () => Cluster.createForTestingOnly({
|
||||
contextName: "some-context-name",
|
||||
id: "some-cluster-id",
|
||||
kubeConfigPath: "/some-path-to-a-kubeconfig",
|
||||
@ -144,7 +143,7 @@ describe("KubeApi", () => {
|
||||
|
||||
const createKubeJsonApi = di.inject(createKubeJsonApiInjectable);
|
||||
|
||||
di.override(hostedClusterInjectable, () => new Cluster({
|
||||
di.override(hostedClusterInjectable, () => Cluster.createForTestingOnly({
|
||||
contextName: "some-context-name",
|
||||
id: "some-cluster-id",
|
||||
kubeConfigPath: "/some-path-to-a-kubeconfig",
|
||||
@ -154,10 +153,6 @@ describe("KubeApi", () => {
|
||||
serverAddress: `http://127.0.0.1:9999`,
|
||||
apiBase: "/api-kube",
|
||||
}));
|
||||
|
||||
const setupAutoRegistration = di.inject(setupAutoRegistrationInjectable);
|
||||
|
||||
setupAutoRegistration.run();
|
||||
});
|
||||
|
||||
describe("deleting pods (namespace scoped resource)", () => {
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { KubeObject } from "@k8slens/kube-object";
|
||||
import { isJsonApiData, isJsonApiDataList, isPartialJsonApiData } from "@k8slens/kube-object";
|
||||
|
||||
describe("KubeObject", () => {
|
||||
describe("isJsonApiData", () => {
|
||||
{
|
||||
type TestCase = [any];
|
||||
type TestCase = [unknown];
|
||||
const tests: TestCase[] = [
|
||||
[false],
|
||||
[true],
|
||||
@ -22,12 +22,12 @@ describe("KubeObject", () => {
|
||||
];
|
||||
|
||||
it.each(tests)("should reject invalid value: %p", (input) => {
|
||||
expect(KubeObject.isJsonApiData(input)).toBe(false);
|
||||
expect(isJsonApiData(input)).toBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
type TestCase = [string, any];
|
||||
type TestCase = [string, unknown];
|
||||
const tests: TestCase[] = [
|
||||
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||
@ -38,12 +38,12 @@ describe("KubeObject", () => {
|
||||
];
|
||||
|
||||
it.each(tests)("should reject with missing: %s", (missingField, input) => {
|
||||
expect(KubeObject.isJsonApiData(input)).toBe(false);
|
||||
expect(isJsonApiData(input)).toBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
type TestCase = [string, any];
|
||||
type TestCase = [string, unknown];
|
||||
const tests: TestCase[] = [
|
||||
["kind", { kind: 1, apiVersion: "", metadata: {}}],
|
||||
["apiVersion", { apiVersion: 1, kind: "", metadata: {}}],
|
||||
@ -65,20 +65,20 @@ describe("KubeObject", () => {
|
||||
];
|
||||
|
||||
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
|
||||
expect(KubeObject.isJsonApiData(input)).toBe(false);
|
||||
expect(isJsonApiData(input)).toBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
it("should accept valid KubeJsonApiData (ignoring other fields)", () => {
|
||||
const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" }}};
|
||||
|
||||
expect(KubeObject.isJsonApiData(valid)).toBe(true);
|
||||
expect(isJsonApiData(valid)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isPartialJsonApiData", () => {
|
||||
{
|
||||
type TestCase = [any];
|
||||
type TestCase = [unknown];
|
||||
const tests: TestCase[] = [
|
||||
[false],
|
||||
[true],
|
||||
@ -91,16 +91,16 @@ describe("KubeObject", () => {
|
||||
];
|
||||
|
||||
it.each(tests)("should reject invalid value: %p", (input) => {
|
||||
expect(KubeObject.isPartialJsonApiData(input)).toBe(false);
|
||||
expect(isPartialJsonApiData(input)).toBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
it("should accept {}", () => {
|
||||
expect(KubeObject.isPartialJsonApiData({})).toBe(true);
|
||||
expect(isPartialJsonApiData({})).toBe(true);
|
||||
});
|
||||
|
||||
{
|
||||
type TestCase = [string, any];
|
||||
type TestCase = [string, unknown];
|
||||
const tests: TestCase[] = [
|
||||
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||
@ -108,12 +108,12 @@ describe("KubeObject", () => {
|
||||
];
|
||||
|
||||
it.each(tests)("should not reject with missing top level field: %s", (missingField, input) => {
|
||||
expect(KubeObject.isPartialJsonApiData(input)).toBe(true);
|
||||
expect(isPartialJsonApiData(input)).toBe(true);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
type TestCase = [string, any];
|
||||
type TestCase = [string, unknown];
|
||||
const tests: TestCase[] = [
|
||||
["kind", { kind: 1, apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||
["apiVersion", { apiVersion: 1, kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||
@ -135,23 +135,23 @@ describe("KubeObject", () => {
|
||||
];
|
||||
|
||||
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
|
||||
expect(KubeObject.isPartialJsonApiData(input)).toBe(false);
|
||||
expect(isPartialJsonApiData(input)).toBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
it("should accept valid Partial<KubeJsonApiData> (ignoring other fields)", () => {
|
||||
const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" }}};
|
||||
|
||||
expect(KubeObject.isPartialJsonApiData(valid)).toBe(true);
|
||||
expect(isPartialJsonApiData(valid)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isJsonApiDataList", () => {
|
||||
function isAny(val: unknown): val is any {
|
||||
function isSomething(val: unknown): val is unknown {
|
||||
return true;
|
||||
}
|
||||
|
||||
function isNotAny(val: unknown): val is any {
|
||||
function isNotSomething(val: unknown): val is unknown {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ describe("KubeObject", () => {
|
||||
}
|
||||
|
||||
{
|
||||
type TestCase = [any];
|
||||
type TestCase = [unknown];
|
||||
const tests: TestCase[] = [
|
||||
[false],
|
||||
[true],
|
||||
@ -174,12 +174,12 @@ describe("KubeObject", () => {
|
||||
];
|
||||
|
||||
it.each(tests)("should reject invalid value: %p", (input) => {
|
||||
expect(KubeObject.isJsonApiDataList(input, isAny)).toBe(false);
|
||||
expect(isJsonApiDataList(input, isSomething)).toBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
type TestCase = [string, any];
|
||||
type TestCase = [string, unknown];
|
||||
const tests: TestCase[] = [
|
||||
["kind", { apiVersion: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}],
|
||||
["apiVersion", { kind: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}],
|
||||
@ -187,12 +187,12 @@ describe("KubeObject", () => {
|
||||
];
|
||||
|
||||
it.each(tests)("should reject with missing: %s", (missingField, input) => {
|
||||
expect(KubeObject.isJsonApiDataList(input, isAny)).toBe(false);
|
||||
expect(isJsonApiDataList(input, isSomething)).toBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
type TestCase = [string, any];
|
||||
type TestCase = [string, unknown];
|
||||
const tests: TestCase[] = [
|
||||
["kind", { kind: 1, items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}],
|
||||
["apiVersion", { kind: "", items: [], apiVersion: 1, metadata: { resourceVersion: "", selfLink: "" }}],
|
||||
@ -206,14 +206,14 @@ describe("KubeObject", () => {
|
||||
];
|
||||
|
||||
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
|
||||
expect(KubeObject.isJsonApiDataList(input, isNotAny)).toBe(false);
|
||||
expect(isJsonApiDataList(input, isNotSomething)).toBe(false);
|
||||
});
|
||||
}
|
||||
|
||||
it("should accept valid KubeJsonApiDataList (ignoring other fields)", () => {
|
||||
const valid = { kind: "", items: [false], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }};
|
||||
|
||||
expect(KubeObject.isJsonApiDataList(valid, isBoolean)).toBe(true);
|
||||
expect(isJsonApiDataList(valid, isBoolean)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -13,10 +13,10 @@ import { parseKubeApi, createKubeApiURL } from "@k8slens/kube-api";
|
||||
import { getOrInsertWith, iter } from "@k8slens/utilities";
|
||||
import type { CreateCustomResourceStore } from "./create-custom-resource-store.injectable";
|
||||
|
||||
export type RegisterableStore<Store> = Store extends KubeObjectStore<any, any, any>
|
||||
export type RegisterableStore<Store> = Store extends KubeObjectStore
|
||||
? Store
|
||||
: never;
|
||||
export type RegisterableApi<Api> = Api extends KubeApi<any, any>
|
||||
export type RegisterableApi<Api> = Api extends KubeApi
|
||||
? Api
|
||||
: never;
|
||||
export type KubeObjectStoreFrom<Api> = Api extends KubeApi<infer KubeObj, infer ApiData>
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import EventEmitter from "events";
|
||||
import type TypedEventEmitter from "typed-emitter";
|
||||
import type { KubeApi } from "@k8slens/kube-api";
|
||||
|
||||
export interface LegacyAutoRegistration {
|
||||
kubeApi: (api: KubeApi<any, any>) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to remove dependency cycles from auto registering of instances
|
||||
*
|
||||
* - Custom Resource Definitions get their own registered store (will need in the future)
|
||||
* - All KubeApi's get auto registered (this should be changed in the future)
|
||||
*/
|
||||
const autoRegistrationEmitterInjectable = getInjectable({
|
||||
id: "auto-registration-emitter",
|
||||
instantiate: (): TypedEventEmitter<LegacyAutoRegistration> => new EventEmitter(),
|
||||
});
|
||||
|
||||
export default autoRegistrationEmitterInjectable;
|
||||
@ -2,9 +2,24 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { DiContainerForInjection } from "@ogre-tools/injectable";
|
||||
import { getInjectable, getInjectionToken } from "@ogre-tools/injectable";
|
||||
import type { KubeObjectStore } from "../kube-object.store";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const kubeObjectStoreInjectionToken = getInjectionToken<KubeObjectStore<any, any, any>>({
|
||||
id: "kube-object-store-token",
|
||||
});
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export interface KubeStoreInjectableParts<Store extends KubeObjectStore<any, any, any>> {
|
||||
id: string;
|
||||
instantiate: (di: DiContainerForInjection) => Store;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const getKubeStoreInjectable = <Store extends KubeObjectStore<any, any, any>>(parts: KubeStoreInjectableParts<Store>) => getInjectable({
|
||||
id: parts.id,
|
||||
instantiate: (di) => parts.instantiate(di),
|
||||
injectionToken: kubeObjectStoreInjectionToken,
|
||||
});
|
||||
|
||||
@ -24,11 +24,11 @@ const createJsonApiInjectable = getInjectable({
|
||||
|
||||
return (config, reqInit) => {
|
||||
if (!config.getRequestOptions) {
|
||||
config.getRequestOptions = async () => {
|
||||
config.getRequestOptions = () => {
|
||||
const agent = new Agent({
|
||||
ca: lensProxyCert.get().cert,
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
agent,
|
||||
};
|
||||
|
||||
@ -19,16 +19,16 @@ export interface CreateKubeApiForLocalClusterConfig {
|
||||
}
|
||||
|
||||
export interface CreateKubeApiForCluster {
|
||||
<Object extends KubeObject, Api extends KubeApi<Object>, Data extends KubeJsonApiDataFor<Object>>(
|
||||
<Kube extends KubeObject, Api extends KubeApi<Kube>, Data extends KubeJsonApiDataFor<Kube>>(
|
||||
cluster: CreateKubeApiForLocalClusterConfig,
|
||||
kubeClass: KubeObjectConstructor<Object, Data>,
|
||||
apiClass: KubeApiConstructor<Object, Api>,
|
||||
kubeClass: KubeObjectConstructor<Kube, Data>,
|
||||
apiClass: KubeApiConstructor<Kube, Api>,
|
||||
): Api;
|
||||
<Object extends KubeObject, Data extends KubeJsonApiDataFor<Object>>(
|
||||
<Kube extends KubeObject, Data extends KubeJsonApiDataFor<Kube>>(
|
||||
cluster: CreateKubeApiForLocalClusterConfig,
|
||||
kubeClass: KubeObjectConstructor<Object, Data>,
|
||||
apiClass?: KubeApiConstructor<Object, KubeApi<Object>>,
|
||||
): KubeApi<Object>;
|
||||
kubeClass: KubeObjectConstructor<Kube, Data>,
|
||||
apiClass?: KubeApiConstructor<Kube, KubeApi<Kube>>,
|
||||
): KubeApi<Kube>;
|
||||
}
|
||||
|
||||
const createKubeApiForClusterInjectable = getInjectable({
|
||||
|
||||
@ -33,19 +33,19 @@ export interface CreateKubeApiForRemoteClusterConfig {
|
||||
agent?: Agent;
|
||||
}
|
||||
|
||||
export type KubeApiConstructor<Object extends KubeObject, Api extends KubeApi<Object>> = new (apiOpts: KubeApiOptions<Object>) => Api;
|
||||
export type KubeApiConstructor<Kube extends KubeObject, Api extends KubeApi<Kube>> = new (apiOpts: KubeApiOptions<Kube>) => Api;
|
||||
|
||||
export interface CreateKubeApiForRemoteCluster {
|
||||
<Object extends KubeObject, Api extends KubeApi<Object>, Data extends KubeJsonApiDataFor<Object>>(
|
||||
<Kube extends KubeObject, Api extends KubeApi<Kube>, Data extends KubeJsonApiDataFor<Kube>>(
|
||||
config: CreateKubeApiForRemoteClusterConfig,
|
||||
kubeClass: KubeObjectConstructor<Object, Data>,
|
||||
apiClass: KubeApiConstructor<Object, Api>,
|
||||
kubeClass: KubeObjectConstructor<Kube, Data>,
|
||||
apiClass: KubeApiConstructor<Kube, Api>,
|
||||
): Api;
|
||||
<Object extends KubeObject, Data extends KubeJsonApiDataFor<Object>>(
|
||||
<Kube extends KubeObject, Data extends KubeJsonApiDataFor<Kube>>(
|
||||
config: CreateKubeApiForRemoteClusterConfig,
|
||||
kubeClass: KubeObjectConstructor<Object, Data>,
|
||||
apiClass?: KubeApiConstructor<Object, KubeApi<Object>>,
|
||||
): KubeApi<Object>;
|
||||
kubeClass: KubeObjectConstructor<Kube, Data>,
|
||||
apiClass?: KubeApiConstructor<Kube, KubeApi<Kube>>,
|
||||
): KubeApi<Kube>;
|
||||
}
|
||||
|
||||
const createKubeApiForRemoteClusterInjectable = getInjectable({
|
||||
|
||||
@ -24,17 +24,17 @@ const createKubeJsonApiInjectable = getInjectable({
|
||||
|
||||
return (config, reqInit) => {
|
||||
if (!config.getRequestOptions) {
|
||||
config.getRequestOptions = async () => {
|
||||
config.getRequestOptions = () => {
|
||||
const agent = new Agent({
|
||||
ca: lensProxyCert.get().cert,
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
agent,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
return new KubeJsonApi(dependencies, config, reqInit);
|
||||
};
|
||||
},
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ClusterRoleBindingApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const clusterRoleBindingApiInjectable = getInjectable({
|
||||
const clusterRoleBindingApiInjectable = getKubeApiInjectable({
|
||||
id: "cluster-role-binding-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "clusterRoleBindingApi is only accessible in certain environments");
|
||||
@ -20,8 +19,6 @@ const clusterRoleBindingApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default clusterRoleBindingApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ClusterRoleApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const clusterRoleApiInjectable = getInjectable({
|
||||
const clusterRoleApiInjectable = getKubeApiInjectable({
|
||||
id: "cluster-role-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "clusterRoleApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const clusterRoleApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default clusterRoleApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ClusterApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const clusterApiInjectable = getInjectable({
|
||||
const clusterApiInjectable = getKubeApiInjectable({
|
||||
id: "cluster-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "clusterApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const clusterApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default clusterApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ComponentStatusApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
|
||||
const componentStatusApiInjectable = getInjectable({
|
||||
const componentStatusApiInjectable = getKubeApiInjectable({
|
||||
id: "component-status-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "componentStatusApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const componentStatusApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default componentStatusApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ConfigMapApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const configMapApiInjectable = getInjectable({
|
||||
const configMapApiInjectable = getKubeApiInjectable({
|
||||
id: "config-map-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "configMapApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const configMapApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default configMapApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { CronJobApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const cronJobApiInjectable = getInjectable({
|
||||
const cronJobApiInjectable = getKubeApiInjectable({
|
||||
id: "cron-job-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "cronJobApi is only available in certain environments");
|
||||
@ -22,8 +21,6 @@ const cronJobApiInjectable = getInjectable({
|
||||
checkPreferredVersion: true,
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default cronJobApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { CustomResourceDefinitionApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
|
||||
const customResourceDefinitionApiInjectable = getInjectable({
|
||||
const customResourceDefinitionApiInjectable = getKubeApiInjectable({
|
||||
id: "custom-resource-definition-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "customResourceDefinitionApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const customResourceDefinitionApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default customResourceDefinitionApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { DaemonSetApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const daemonSetApiInjectable = getInjectable({
|
||||
const daemonSetApiInjectable = getKubeApiInjectable({
|
||||
id: "daemon-set-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "daemonSetApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const daemonSetApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default daemonSetApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { DeploymentApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const deploymentApiInjectable = getInjectable({
|
||||
const deploymentApiInjectable = getKubeApiInjectable({
|
||||
id: "deployment-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "deploymentApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const deploymentApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default deploymentApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { EndpointsApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const endpointsApiInjectable = getInjectable({
|
||||
const endpointsApiInjectable = getKubeApiInjectable({
|
||||
id: "endpoints-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "endpointsApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const endpointsApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default endpointsApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { KubeEventApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const kubeEventApiInjectable = getInjectable({
|
||||
const kubeEventApiInjectable = getKubeApiInjectable({
|
||||
id: "kube-event-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "kubeEventApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const kubeEventApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default kubeEventApiInjectable;
|
||||
|
||||
@ -3,9 +3,8 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
import { array } from "@k8slens/utilities";
|
||||
import autoBind from "auto-bind";
|
||||
import Joi from "joi";
|
||||
import { z } from "zod";
|
||||
|
||||
export interface RawHelmChart {
|
||||
apiVersion: string;
|
||||
@ -31,132 +30,51 @@ export interface RawHelmChart {
|
||||
annotations?: Record<string, string>;
|
||||
}
|
||||
|
||||
const helmChartMaintainerValidator = Joi.object<HelmChartMaintainer>({
|
||||
name: Joi
|
||||
.string()
|
||||
.required(),
|
||||
email: Joi
|
||||
.string()
|
||||
.required(),
|
||||
url: Joi
|
||||
.string()
|
||||
.optional(),
|
||||
const helmChartMaintainerSchema = z.object({
|
||||
name: z.string(),
|
||||
email: z.string(),
|
||||
url: z.string().optional(),
|
||||
});
|
||||
|
||||
const helmChartDependencyValidator = Joi.object<HelmChartDependency, true, RawHelmChartDependency>({
|
||||
name: Joi
|
||||
.string()
|
||||
.required(),
|
||||
repository: Joi
|
||||
.string()
|
||||
.required(),
|
||||
condition: Joi
|
||||
.string()
|
||||
.optional(),
|
||||
version: Joi
|
||||
.string()
|
||||
.required(),
|
||||
tags: Joi
|
||||
.array()
|
||||
.items(Joi.string())
|
||||
.default(() => ([])),
|
||||
const helmChartDependencySchema = z.object({
|
||||
name: z.string(),
|
||||
repository: z.string(),
|
||||
condition: z.string().optional(),
|
||||
version: z.string(),
|
||||
tags: z.array(z.string()).default(() => []),
|
||||
});
|
||||
|
||||
const helmChartValidator = Joi.object<HelmChart, true, RawHelmChart>({
|
||||
apiVersion: Joi
|
||||
.string()
|
||||
.required(),
|
||||
name: Joi
|
||||
.string()
|
||||
.required(),
|
||||
version: Joi
|
||||
.string()
|
||||
.required(),
|
||||
repo: Joi
|
||||
.string()
|
||||
.required(),
|
||||
created: Joi
|
||||
.string()
|
||||
.required(),
|
||||
digest: Joi
|
||||
.string()
|
||||
const helmChartValidator = z.object({
|
||||
apiVersion: z.string(),
|
||||
name: z.string(),
|
||||
version: z.string(),
|
||||
repo: z.string(),
|
||||
created: z.string(),
|
||||
digest: z.string().optional(),
|
||||
kubeVersion: z.string()
|
||||
.optional(),
|
||||
kubeVersion: Joi
|
||||
.string()
|
||||
.optional(),
|
||||
description: Joi
|
||||
.string()
|
||||
description: z.string()
|
||||
.default(""),
|
||||
home: Joi
|
||||
.string()
|
||||
home: z.string()
|
||||
.optional(),
|
||||
engine: Joi
|
||||
.string()
|
||||
engine: z.string()
|
||||
.optional(),
|
||||
icon: Joi
|
||||
.string()
|
||||
icon: z.string()
|
||||
.optional(),
|
||||
appVersion: Joi
|
||||
.string()
|
||||
appVersion: z.string()
|
||||
.optional(),
|
||||
tillerVersion: Joi
|
||||
.string()
|
||||
tillerVersion: z.string()
|
||||
.optional(),
|
||||
type: Joi
|
||||
.string()
|
||||
type: z.string()
|
||||
.optional(),
|
||||
deprecated: Joi
|
||||
.boolean()
|
||||
deprecated: z.boolean()
|
||||
.default(false),
|
||||
keywords: Joi
|
||||
.array()
|
||||
.items(Joi.string())
|
||||
.options({
|
||||
stripUnknown: {
|
||||
arrays: true,
|
||||
},
|
||||
})
|
||||
.default(() => ([])),
|
||||
sources: Joi
|
||||
.array()
|
||||
.items(Joi.string())
|
||||
.options({
|
||||
stripUnknown: {
|
||||
arrays: true,
|
||||
},
|
||||
})
|
||||
.default(() => ([])),
|
||||
urls: Joi
|
||||
.array()
|
||||
.items(Joi.string())
|
||||
.options({
|
||||
stripUnknown: {
|
||||
arrays: true,
|
||||
},
|
||||
})
|
||||
.default(() => ([])),
|
||||
maintainers: Joi
|
||||
.array()
|
||||
.items(helmChartMaintainerValidator)
|
||||
.options({
|
||||
stripUnknown: {
|
||||
arrays: true,
|
||||
},
|
||||
})
|
||||
.default(() => ([])),
|
||||
dependencies: Joi
|
||||
.array()
|
||||
.items(helmChartDependencyValidator)
|
||||
.options({
|
||||
stripUnknown: {
|
||||
arrays: true,
|
||||
},
|
||||
})
|
||||
.default(() => ([])),
|
||||
annotations: Joi
|
||||
.object({})
|
||||
.pattern(/.*/, Joi.string())
|
||||
.default(() => ({})),
|
||||
keywords: z.array(z.string()).default(() => ([])),
|
||||
sources: z.array(z.string()).default(() => ([])),
|
||||
urls: z.array(z.string()).default(() => ([])),
|
||||
maintainers: z.array(helmChartMaintainerSchema).default(() => ([])),
|
||||
dependencies: z.array(helmChartDependencySchema).default(() => ([])),
|
||||
annotations: z.record(z.string()).default(() => ({})),
|
||||
});
|
||||
|
||||
export interface HelmChartCreateOpts {
|
||||
@ -256,31 +174,17 @@ export class HelmChart implements HelmChartData {
|
||||
static create(data: RawHelmChart): HelmChart;
|
||||
static create(data: RawHelmChart, opts?: HelmChartCreateOpts): HelmChart | undefined;
|
||||
static create(data: RawHelmChart, { onError = "throw" }: HelmChartCreateOpts = {}): HelmChart | undefined {
|
||||
const result = helmChartValidator.validate(data, {
|
||||
abortEarly: false,
|
||||
});
|
||||
const result = helmChartValidator.safeParse(data);
|
||||
|
||||
if (!result.error) {
|
||||
return new HelmChart(result.value);
|
||||
if (result.success) {
|
||||
return new HelmChart(result.data);
|
||||
}
|
||||
|
||||
const [actualErrors, unknownDetails] = array.bifurcate(result.error.details, ({ type }) => type === "object.unknown");
|
||||
|
||||
if (unknownDetails.length > 0) {
|
||||
console.warn("HelmChart data has unexpected fields", { original: data, unknownFields: unknownDetails.flatMap(d => d.path) });
|
||||
}
|
||||
|
||||
if (actualErrors.length === 0) {
|
||||
return new HelmChart(result.value as unknown as HelmChartData);
|
||||
}
|
||||
|
||||
const validationError = new Joi.ValidationError(actualErrors.map(er => er.message).join(". "), actualErrors, result.error._original);
|
||||
|
||||
if (onError === "throw") {
|
||||
throw validationError;
|
||||
throw result.error;
|
||||
}
|
||||
|
||||
console.warn("[HELM-CHART]: failed to validate data", data, validationError);
|
||||
console.warn("[HELM-CHART]: failed to validate data", data, result.error);
|
||||
|
||||
return undefined;
|
||||
}
|
||||
@ -289,16 +193,20 @@ export class HelmChart implements HelmChartData {
|
||||
const digestPart = this.digest
|
||||
? `+${this.digest}`
|
||||
: "";
|
||||
const version = this.getAppVersion();
|
||||
const versionId = version
|
||||
? `@${version}`
|
||||
: "";
|
||||
|
||||
return `${this.repo}:${this.apiVersion}/${this.name}@${this.getAppVersion()}${digestPart}`;
|
||||
return `${this.repo}:${this.apiVersion}/${this.name}${versionId}${digestPart}`;
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
getFullName(seperator = "/"): string {
|
||||
return [this.getRepository(), this.getName()].join(seperator);
|
||||
getFullName(separator = "/"): string {
|
||||
return [this.getRepository(), this.getName()].join(separator);
|
||||
}
|
||||
|
||||
getDescription(): string {
|
||||
|
||||
@ -9,7 +9,7 @@ import apiBaseInjectable from "../../api-base.injectable";
|
||||
|
||||
const requestReadmeEndpoint = urlBuilderFor("/v2/charts/:repo/:name/readme");
|
||||
|
||||
export type RequestHelmChartReadme = (repo: string, name: string, version?: string) => AsyncResult<string>;
|
||||
export type RequestHelmChartReadme = (repo: string, name: string, version?: string) => AsyncResult<string, string>;
|
||||
|
||||
const requestHelmChartReadmeInjectable = getInjectable({
|
||||
id: "request-helm-chart-readme",
|
||||
|
||||
@ -9,7 +9,7 @@ import apiBaseInjectable from "../../api-base.injectable";
|
||||
|
||||
const requestValuesEndpoint = urlBuilderFor("/v2/charts/:repo/:name/values");
|
||||
|
||||
export type RequestHelmChartValues = (repo: string, name: string, version: string) => AsyncResult<string>;
|
||||
export type RequestHelmChartValues = (repo: string, name: string, version: string) => AsyncResult<string, string>;
|
||||
|
||||
const requestHelmChartValuesInjectable = getInjectable({
|
||||
id: "request-helm-chart-values",
|
||||
|
||||
@ -38,10 +38,10 @@ const requestHelmReleaseUpdateInjectable = getInjectable({
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
return { callWasSuccessful: false, error: e };
|
||||
return { isOk: false, error: e };
|
||||
}
|
||||
|
||||
return { callWasSuccessful: true };
|
||||
return { isOk: true };
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { HorizontalPodAutoscalerApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const horizontalPodAutoscalerApiInjectable = getInjectable({
|
||||
const horizontalPodAutoscalerApiInjectable = getKubeApiInjectable({
|
||||
id: "horizontal-pod-autoscaler-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "horizontalPodAutoscalerApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const horizontalPodAutoscalerApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default horizontalPodAutoscalerApiInjectable;
|
||||
|
||||
@ -2,20 +2,23 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { IngressClassApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import assert from "assert";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
|
||||
const ingressClassApiInjectable = getInjectable({
|
||||
const ingressClassApiInjectable = getKubeApiInjectable({
|
||||
id: "ingress-class-api",
|
||||
instantiate: (di) => new IngressClassApi({
|
||||
logger: di.inject(loggerInjectionToken),
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
}),
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "ingressClassApi is only available in certain environments");
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
return new IngressClassApi({
|
||||
logger: di.inject(loggerInjectionToken),
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
export default ingressClassApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { IngressApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const ingressApiInjectable = getInjectable({
|
||||
const ingressApiInjectable = getKubeApiInjectable({
|
||||
id: "ingress-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "ingressApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const ingressApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default ingressApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { JobApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const jobApiInjectable = getInjectable({
|
||||
const jobApiInjectable = getKubeApiInjectable({
|
||||
id: "job-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "jobApi is only available in certain environments");
|
||||
@ -22,8 +21,6 @@ const jobApiInjectable = getInjectable({
|
||||
checkPreferredVersion: true,
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default jobApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { LeaseApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const leaseApiInjectable = getInjectable({
|
||||
const leaseApiInjectable = getKubeApiInjectable({
|
||||
id: "lease-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "leaseApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const leaseApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default leaseApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { LimitRangeApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const limitRangeApiInjectable = getInjectable({
|
||||
const limitRangeApiInjectable = getKubeApiInjectable({
|
||||
id: "limit-range-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "limitRangeApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const limitRangeApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default limitRangeApiInjectable;
|
||||
|
||||
@ -2,26 +2,23 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { MutatingWebhookConfigurationApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const mutatingWebhookConfigurationApiInjectable = getInjectable({
|
||||
const mutatingWebhookConfigurationApiInjectable = getKubeApiInjectable({
|
||||
id: "mutating-webhook-configuration",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "mutatingWebhookApi is only available in certain environments");
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "mutatingWebhookConfigurationApi is only available in certain environments");
|
||||
|
||||
return new MutatingWebhookConfigurationApi({
|
||||
logger: di.inject(loggerInjectionToken),
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default mutatingWebhookConfigurationApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { NamespaceApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const namespaceApiInjectable = getInjectable({
|
||||
const namespaceApiInjectable = getKubeApiInjectable({
|
||||
id: "namespace-api",
|
||||
|
||||
instantiate: (di) => {
|
||||
@ -21,8 +20,6 @@ const namespaceApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default namespaceApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { NetworkPolicyApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const networkPolicyApiInjectable = getInjectable({
|
||||
const networkPolicyApiInjectable = getKubeApiInjectable({
|
||||
id: "network-policy-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "networkPolicyApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const networkPolicyApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default networkPolicyApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { NodeApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const nodeApiInjectable = getInjectable({
|
||||
const nodeApiInjectable = getKubeApiInjectable({
|
||||
id: "node-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "nodeApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const nodeApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default nodeApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { PersistentVolumeClaimApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const persistentVolumeClaimApiInjectable = getInjectable({
|
||||
const persistentVolumeClaimApiInjectable = getKubeApiInjectable({
|
||||
id: "persistent-volume-claim-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "persistentVolumeClaimApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const persistentVolumeClaimApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default persistentVolumeClaimApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { PersistentVolumeApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const persistentVolumeApiInjectable = getInjectable({
|
||||
const persistentVolumeApiInjectable = getKubeApiInjectable({
|
||||
id: "persistent-volume-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "persistentVolumeApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const persistentVolumeApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default persistentVolumeApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { PodDisruptionBudgetApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const podDisruptionBudgetApiInjectable = getInjectable({
|
||||
const podDisruptionBudgetApiInjectable = getKubeApiInjectable({
|
||||
id: "pod-disruption-budget-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "podDisruptionBudgetApi is only available in certain environments");
|
||||
@ -28,8 +27,6 @@ const podDisruptionBudgetApiInjectable = getInjectable({
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default podDisruptionBudgetApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { PodMetricsApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const podMetricsApiInjectable = getInjectable({
|
||||
const podMetricsApiInjectable = getKubeApiInjectable({
|
||||
id: "pod-metrics-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "podMetricsApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const podMetricsApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default podMetricsApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { PodSecurityPolicyApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const podSecurityPolicyApiInjectable = getInjectable({
|
||||
const podSecurityPolicyApiInjectable = getKubeApiInjectable({
|
||||
id: "pod-security-policy-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "podSecurityPolicyApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const podSecurityPolicyApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default podSecurityPolicyApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { PodApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const podApiInjectable = getInjectable({
|
||||
const podApiInjectable = getKubeApiInjectable({
|
||||
id: "pod-api",
|
||||
|
||||
instantiate: (di) => {
|
||||
@ -21,8 +20,6 @@ const podApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default podApiInjectable;
|
||||
|
||||
@ -2,26 +2,23 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { PriorityClassApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const priorityClassApiInjectable = getInjectable({
|
||||
const priorityClassApiInjectable = getKubeApiInjectable({
|
||||
id: "priority-class-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "PriorityClassApi is only available in certain environments");
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "priorityClassApi is only available in certain environments");
|
||||
|
||||
return new PriorityClassApi({
|
||||
logger: di.inject(loggerInjectionToken),
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default priorityClassApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ReplicaSetApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const replicaSetApiInjectable = getInjectable({
|
||||
const replicaSetApiInjectable = getKubeApiInjectable({
|
||||
id: "replica-set-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "replicaSetApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const replicaSetApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default replicaSetApiInjectable;
|
||||
|
||||
@ -2,22 +2,23 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { ReplicationControllerApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import assert from "assert";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
|
||||
const replicationControllerApiInjectable = getInjectable({
|
||||
const replicationControllerApiInjectable = getKubeApiInjectable({
|
||||
id: "replication-controller-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "replicationControllerApi is only available in certain environments");
|
||||
|
||||
return new ReplicationControllerApi({
|
||||
logger: di.inject(loggerInjectionToken),
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default replicationControllerApiInjectable;
|
||||
|
||||
@ -25,20 +25,20 @@ const requestKubeObjectPatchInjectable = getInjectable({
|
||||
},
|
||||
})) as Result<string, string>;
|
||||
|
||||
if (!result.callWasSuccessful) {
|
||||
if (!result.isOk) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = JSON.parse(result.response) as KubeJsonApiData;
|
||||
const response = JSON.parse(result.value) as KubeJsonApiData;
|
||||
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
isOk: true,
|
||||
response,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
isOk: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
|
||||
@ -17,20 +17,20 @@ const requestKubeObjectCreationInjectable = getInjectable({
|
||||
return async (data) => {
|
||||
const result = await apiBase.post("/stack", { data }) as Result<string, string>;
|
||||
|
||||
if (!result.callWasSuccessful) {
|
||||
if (!result.isOk) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = JSON.parse(result.response);
|
||||
const response = JSON.parse(result.value) as KubeJsonApiData;
|
||||
|
||||
return {
|
||||
callWasSuccessful: true,
|
||||
isOk: true,
|
||||
response,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
callWasSuccessful: false,
|
||||
isOk: false,
|
||||
error: String(error),
|
||||
};
|
||||
}
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ResourceQuotaApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const resourceQuotaApiInjectable = getInjectable({
|
||||
const resourceQuotaApiInjectable = getKubeApiInjectable({
|
||||
id: "resource-quota-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "resourceQuotaApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const resourceQuotaApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default resourceQuotaApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { RoleBindingApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const roleBindingApiInjectable = getInjectable({
|
||||
const roleBindingApiInjectable = getKubeApiInjectable({
|
||||
id: "role-binding-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "roleBindingApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const roleBindingApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default roleBindingApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { RoleApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const roleApiInjectable = getInjectable({
|
||||
const roleApiInjectable = getKubeApiInjectable({
|
||||
id: "role-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "roleApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const roleApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default roleApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { RuntimeClassApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const runtimeClassApiInjectable = getInjectable({
|
||||
const runtimeClassApiInjectable = getKubeApiInjectable({
|
||||
id: "runtime-class-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "RuntimeClassApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const runtimeClassApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default runtimeClassApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { SecretApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const secretApiInjectable = getInjectable({
|
||||
const secretApiInjectable = getKubeApiInjectable({
|
||||
id: "secret-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "secretApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const secretApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default secretApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { SelfSubjectRulesReviewApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const selfSubjectRulesReviewApiInjectable = getInjectable({
|
||||
const selfSubjectRulesReviewApiInjectable = getKubeApiInjectable({
|
||||
id: "self-subject-rules-review-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "selfSubjectRulesReviewApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const selfSubjectRulesReviewApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default selfSubjectRulesReviewApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ServiceAccountApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const serviceAccountApiInjectable = getInjectable({
|
||||
const serviceAccountApiInjectable = getKubeApiInjectable({
|
||||
id: "service-account-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "serviceAccountApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const serviceAccountApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default serviceAccountApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ServiceApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const serviceApiInjectable = getInjectable({
|
||||
const serviceApiInjectable = getKubeApiInjectable({
|
||||
id: "service-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "serviceApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const serviceApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default serviceApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { StatefulSetApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const statefulSetApiInjectable = getInjectable({
|
||||
const statefulSetApiInjectable = getKubeApiInjectable({
|
||||
id: "stateful-set-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "statefulSetApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const statefulSetApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default statefulSetApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { StorageClassApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const storageClassApiInjectable = getInjectable({
|
||||
const storageClassApiInjectable = getKubeApiInjectable({
|
||||
id: "storage-class-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "storageClassApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const storageClassApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default storageClassApiInjectable;
|
||||
|
||||
@ -2,26 +2,23 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { ValidatingWebhookConfigurationApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const validatingWebhookConfigurationApiInjectable = getInjectable({
|
||||
id: "validating-webhook-configuration",
|
||||
const validatingWebhookConfigurationApiInjectable = getKubeApiInjectable({
|
||||
id: "validating-webhook-configuration-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "validatingWebhookApi is only available in certain environments");
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "validatingWebhookConfigurationApi is only available in certain environments");
|
||||
|
||||
return new ValidatingWebhookConfigurationApi({
|
||||
logger: di.inject(loggerInjectionToken),
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default validatingWebhookConfigurationApiInjectable;
|
||||
|
||||
@ -2,15 +2,14 @@
|
||||
* 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 assert from "assert";
|
||||
import { storesAndApisCanBeCreatedInjectionToken } from "../stores-apis-can-be-created.token";
|
||||
import { VerticalPodAutoscalerApi } from "@k8slens/kube-api";
|
||||
import { kubeApiInjectionToken } from "@k8slens/kube-api-specifics";
|
||||
import { getKubeApiInjectable } from "@k8slens/kube-api-specifics";
|
||||
import { loggerInjectionToken } from "@k8slens/logger";
|
||||
import maybeKubeApiInjectable from "../maybe-kube-api.injectable";
|
||||
|
||||
const verticalPodAutoscalerApiInjectable = getInjectable({
|
||||
const verticalPodAutoscalerApiInjectable = getKubeApiInjectable({
|
||||
id: "vertical-pod-autoscaler-api",
|
||||
instantiate: (di) => {
|
||||
assert(di.inject(storesAndApisCanBeCreatedInjectionToken), "verticalPodAutoscalerApi is only available in certain environments");
|
||||
@ -20,8 +19,6 @@ const verticalPodAutoscalerApiInjectable = getInjectable({
|
||||
maybeKubeApi: di.inject(maybeKubeApiInjectable),
|
||||
});
|
||||
},
|
||||
|
||||
injectionToken: kubeApiInjectionToken,
|
||||
});
|
||||
|
||||
export default verticalPodAutoscalerApiInjectable;
|
||||
|
||||
@ -97,6 +97,14 @@ export class KubeObjectStore<
|
||||
|
||||
private readonly loadedNamespaces = observable.box<string[]>();
|
||||
|
||||
static create<Api>(
|
||||
dependencies: KubeObjectStoreDependencies,
|
||||
api: Api,
|
||||
opts?: KubeObjectStoreOptions,
|
||||
): Api extends KubeApi<infer Kube, infer Data> ? KubeObjectStore<Kube, Api, Data> : never {
|
||||
return new KubeObjectStore(dependencies, api as KubeApi, opts) as never;
|
||||
}
|
||||
|
||||
constructor(
|
||||
protected readonly dependencies: KubeObjectStoreDependencies,
|
||||
public readonly api: A,
|
||||
@ -297,7 +305,7 @@ export class KubeObjectStore<
|
||||
return items;
|
||||
}
|
||||
|
||||
protected resetOnError(error: any) {
|
||||
protected resetOnError(error: unknown) {
|
||||
if (error) this.reset();
|
||||
}
|
||||
|
||||
|
||||
@ -16,8 +16,8 @@ import type { ReadFile } from "../fs/read-file.injectable";
|
||||
import { hasTypedProperty, isObject } from "@k8slens/utilities";
|
||||
|
||||
export interface ResourceApplyingStack {
|
||||
kubectlApplyFolder(folderPath: string, templateContext?: any, extraArgs?: string[]): Promise<string>;
|
||||
kubectlDeleteFolder(folderPath: string, templateContext?: any, extraArgs?: string[]): Promise<string>;
|
||||
kubectlApplyFolder(folderPath: string, templateContext?: unknown, extraArgs?: string[]): Promise<string>;
|
||||
kubectlDeleteFolder(folderPath: string, templateContext?: unknown, extraArgs?: string[]): Promise<string>;
|
||||
}
|
||||
|
||||
export interface ResourceStackDependencies {
|
||||
@ -41,12 +41,12 @@ export class ResourceStack {
|
||||
* @param folderPath folder path that is searched for files defining kubernetes resources.
|
||||
* @param templateContext sets the template parameters that are to be applied to any templated kubernetes resources that are to be applied.
|
||||
*/
|
||||
async kubectlApplyFolder(folderPath: string, templateContext?: any, extraArgs?: string[]): Promise<string> {
|
||||
async kubectlApplyFolder(folderPath: string, templateContext?: unknown, extraArgs?: string[]): Promise<string> {
|
||||
const resources = await this.renderTemplates(folderPath, templateContext);
|
||||
const result = await this.applyResources(resources, extraArgs);
|
||||
|
||||
if (result.callWasSuccessful) {
|
||||
return result.response;
|
||||
if (result.isOk) {
|
||||
return result.value;
|
||||
}
|
||||
|
||||
this.dependencies.logger.warn(`[RESOURCE-STACK]: failed to apply resources: ${result.error}`);
|
||||
@ -59,12 +59,12 @@ export class ResourceStack {
|
||||
* @param folderPath folder path that is searched for files defining kubernetes resources.
|
||||
* @param templateContext sets the template parameters that are to be applied to any templated kubernetes resources that are to be applied.
|
||||
*/
|
||||
async kubectlDeleteFolder(folderPath: string, templateContext?: any, extraArgs?: string[]): Promise<string> {
|
||||
async kubectlDeleteFolder(folderPath: string, templateContext?: unknown, extraArgs?: string[]): Promise<string> {
|
||||
const resources = await this.renderTemplates(folderPath, templateContext);
|
||||
const result = await this.deleteResources(resources, extraArgs);
|
||||
|
||||
if (result.callWasSuccessful) {
|
||||
return result.response;
|
||||
if (result.isOk) {
|
||||
return result.value;
|
||||
}
|
||||
|
||||
this.dependencies.logger.warn(`[RESOURCE-STACK]: failed to delete resources: ${result.error}`);
|
||||
@ -100,7 +100,7 @@ export class ResourceStack {
|
||||
return [];
|
||||
}
|
||||
|
||||
protected async renderTemplates(folderPath: string, templateContext: any): Promise<string[]> {
|
||||
protected async renderTemplates(folderPath: string, templateContext: unknown): Promise<string[]> {
|
||||
const resources: string[] = [];
|
||||
const di = getLegacyGlobalDiForExtensionApi();
|
||||
const productName = di.inject(productNameInjectable);
|
||||
|
||||
@ -7,64 +7,55 @@ import { KubeConfig } from "@kubernetes/client-node";
|
||||
import yaml from "js-yaml";
|
||||
import type { Cluster, Context, User } from "@kubernetes/client-node/dist/config_types";
|
||||
import { newClusters, newContexts, newUsers } from "@kubernetes/client-node/dist/config_types";
|
||||
import type { Result } from "@k8slens/utilities";
|
||||
import { isDefined } from "@k8slens/utilities";
|
||||
import Joi from "joi";
|
||||
import type { PartialDeep } from "type-fest";
|
||||
import z from "zod";
|
||||
import type { ZodError } from "zod";
|
||||
|
||||
const clusterSchema = Joi.object({
|
||||
name: Joi
|
||||
const userSchema = z.object({
|
||||
name: z.string()
|
||||
.min(1),
|
||||
});
|
||||
|
||||
const clusterSchema = z.object({
|
||||
name: z
|
||||
.string()
|
||||
.min(1)
|
||||
.required(),
|
||||
cluster: Joi
|
||||
.min(1),
|
||||
cluster: z
|
||||
.object({
|
||||
server: Joi
|
||||
server: z
|
||||
.string()
|
||||
.min(1)
|
||||
.required(),
|
||||
})
|
||||
.required(),
|
||||
.min(1),
|
||||
}),
|
||||
});
|
||||
|
||||
const userSchema = Joi.object({
|
||||
name: Joi.string()
|
||||
.min(1)
|
||||
.required(),
|
||||
});
|
||||
|
||||
const contextSchema = Joi.object({
|
||||
name: Joi.string()
|
||||
.min(1)
|
||||
.required(),
|
||||
context: Joi.object({
|
||||
cluster: Joi.string()
|
||||
.min(1)
|
||||
.required(),
|
||||
user: Joi.string()
|
||||
.min(1)
|
||||
.required(),
|
||||
const contextSchema = z.object({
|
||||
name: z.string()
|
||||
.min(1),
|
||||
context: z.object({
|
||||
cluster: z.string()
|
||||
.min(1),
|
||||
user: z.string()
|
||||
.min(1),
|
||||
}),
|
||||
});
|
||||
|
||||
const kubeConfigSchema = Joi.object({
|
||||
users: Joi
|
||||
.array()
|
||||
.items(userSchema)
|
||||
const kubeConfigSchema = z.object({
|
||||
users: z
|
||||
.array(userSchema)
|
||||
.optional(),
|
||||
clusters: Joi
|
||||
.array()
|
||||
.items(clusterSchema)
|
||||
clusters: z
|
||||
.array(clusterSchema)
|
||||
.optional(),
|
||||
contexts: Joi
|
||||
.array()
|
||||
.items(contextSchema)
|
||||
contexts: z
|
||||
.array(contextSchema)
|
||||
.optional(),
|
||||
"current-context": Joi
|
||||
"current-context": z
|
||||
.string()
|
||||
.min(1)
|
||||
.optional(),
|
||||
})
|
||||
.required();
|
||||
});
|
||||
|
||||
interface KubeConfigOptions {
|
||||
clusters: Cluster[];
|
||||
@ -73,37 +64,25 @@ interface KubeConfigOptions {
|
||||
currentContext?: string;
|
||||
}
|
||||
|
||||
interface OptionsResult {
|
||||
options: KubeConfigOptions;
|
||||
error: Joi.ValidationError | undefined;
|
||||
}
|
||||
|
||||
function loadToOptions(rawYaml: string): OptionsResult {
|
||||
function loadToOptions(rawYaml: string): Result<KubeConfigOptions, ZodError<unknown>> {
|
||||
const parsed = yaml.load(rawYaml);
|
||||
const { error } = kubeConfigSchema.validate(parsed, {
|
||||
abortEarly: false,
|
||||
allowUnknown: true,
|
||||
});
|
||||
const { value } = kubeConfigSchema.validate(parsed, {
|
||||
abortEarly: false,
|
||||
allowUnknown: true,
|
||||
stripUnknown: {
|
||||
arrays: true,
|
||||
},
|
||||
});
|
||||
const {
|
||||
clusters: rawClusters,
|
||||
users: rawUsers,
|
||||
contexts: rawContexts,
|
||||
"current-context": currentContext,
|
||||
} = value ?? {};
|
||||
const clusters = newClusters(rawClusters);
|
||||
const users = newUsers(rawUsers);
|
||||
const contexts = newContexts(rawContexts);
|
||||
const configParseResult = kubeConfigSchema.safeParse(parsed);
|
||||
|
||||
if (configParseResult.success === false) {
|
||||
return {
|
||||
isOk: false,
|
||||
error: configParseResult.error,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
options: { clusters, users, contexts, currentContext },
|
||||
error,
|
||||
isOk: true,
|
||||
value: {
|
||||
clusters: newClusters(configParseResult.data.clusters),
|
||||
users: newUsers(configParseResult.data.users),
|
||||
contexts: newContexts(configParseResult.data.contexts),
|
||||
currentContext: configParseResult.data["current-context"],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -116,33 +95,32 @@ export function loadFromOptions(options: KubeConfigOptions): KubeConfig {
|
||||
return kc;
|
||||
}
|
||||
|
||||
export interface ConfigResult {
|
||||
config: KubeConfig;
|
||||
error: Joi.ValidationError | undefined;
|
||||
}
|
||||
export function loadConfigFromString(content: string): Result<KubeConfig, ZodError<unknown>> {
|
||||
const loadResult = loadToOptions(content);
|
||||
|
||||
export function loadConfigFromString(content: string): ConfigResult {
|
||||
const { options, error } = loadToOptions(content);
|
||||
if (loadResult.isOk === false) {
|
||||
return loadResult;
|
||||
}
|
||||
|
||||
return {
|
||||
config: loadFromOptions(options),
|
||||
error,
|
||||
isOk: true,
|
||||
value: loadFromOptions(loadResult.value),
|
||||
};
|
||||
}
|
||||
|
||||
export function loadValidatedConfig(content: string, contextName: string): ValidateKubeConfigResult {
|
||||
const { options, error } = loadToOptions(content);
|
||||
export function loadValidatedConfig(content: string, contextName: string): Result<PartialKubeConfig, ZodError<unknown> | string> {
|
||||
const result = loadToOptions(content);
|
||||
|
||||
if (error) {
|
||||
return { error };
|
||||
if (result.isOk === false) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return validateKubeConfig(loadFromOptions(options), contextName);
|
||||
return validateKubeConfig(loadFromOptions(result.value), contextName);
|
||||
}
|
||||
|
||||
export interface SplitConfigEntry {
|
||||
config: KubeConfig;
|
||||
validationResult: ValidateKubeConfigResult;
|
||||
validationResult: Result<PartialKubeConfig, ZodError<unknown> | string>;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -212,8 +190,8 @@ export function dumpConfigYaml(kubeConfig: PartialDeep<KubeConfig>): string {
|
||||
"client-certificate": user.certFile,
|
||||
"client-key-data": user.keyData,
|
||||
"client-key": user.keyFile,
|
||||
"auth-provider": user.authProvider,
|
||||
exec: user.exec,
|
||||
"auth-provider": user.authProvider as unknown,
|
||||
exec: user.exec as unknown,
|
||||
token: user.token,
|
||||
username: user.username,
|
||||
password: user.password,
|
||||
@ -233,26 +211,24 @@ export function dumpConfigYaml(kubeConfig: PartialDeep<KubeConfig>): string {
|
||||
return yaml.dump(config, { skipInvalid: true });
|
||||
}
|
||||
|
||||
export type ValidateKubeConfigResult = {
|
||||
error: Error;
|
||||
} | {
|
||||
error?: undefined;
|
||||
context: Context;
|
||||
cluster: Cluster;
|
||||
user: User;
|
||||
};
|
||||
export interface PartialKubeConfig {
|
||||
readonly context: Context;
|
||||
readonly cluster: Cluster;
|
||||
readonly user: User;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if `config` has valid `Context`, `User`, `Cluster`, and `exec` fields (if present when required)
|
||||
*
|
||||
* Note: This function returns an error instead of throwing it, returning `undefined` if the validation passes
|
||||
*/
|
||||
export function validateKubeConfig(config: KubeConfig, contextName: string): ValidateKubeConfigResult {
|
||||
export function validateKubeConfig(config: KubeConfig, contextName: string): Result<PartialKubeConfig, string> {
|
||||
const context = config.getContextObject(contextName);
|
||||
|
||||
if (!context) {
|
||||
return {
|
||||
error: new Error(`No valid context object provided in kubeconfig for context '${contextName}'`),
|
||||
isOk: false,
|
||||
error: `No valid context object provided in kubeconfig for context '${contextName}'`,
|
||||
};
|
||||
}
|
||||
|
||||
@ -260,7 +236,8 @@ export function validateKubeConfig(config: KubeConfig, contextName: string): Val
|
||||
|
||||
if (!cluster) {
|
||||
return {
|
||||
error: new Error(`No valid cluster object provided in kubeconfig for context '${contextName}'`),
|
||||
isOk: false,
|
||||
error: `No valid cluster object provided in kubeconfig for context '${contextName}'`,
|
||||
};
|
||||
}
|
||||
|
||||
@ -268,9 +245,13 @@ export function validateKubeConfig(config: KubeConfig, contextName: string): Val
|
||||
|
||||
if (!user) {
|
||||
return {
|
||||
error: new Error(`No valid user object provided in kubeconfig for context '${contextName}'`),
|
||||
isOk: false,
|
||||
error: `No valid user object provided in kubeconfig for context '${contextName}'`,
|
||||
};
|
||||
}
|
||||
|
||||
return { cluster, user, context };
|
||||
return {
|
||||
isOk: true,
|
||||
value: { cluster, user, context },
|
||||
};
|
||||
}
|
||||
|
||||
@ -2,13 +2,15 @@
|
||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
import type { AsyncResult } from "@k8slens/utilities";
|
||||
import type { KubeConfig } from "@kubernetes/client-node";
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import type { ZodError } from "zod";
|
||||
import readFileInjectable from "../fs/read-file.injectable";
|
||||
import type { ConfigResult } from "../kube-helpers";
|
||||
import { loadConfigFromString } from "../kube-helpers";
|
||||
import resolveTildeInjectable from "../path/resolve-tilde.injectable";
|
||||
|
||||
export type LoadConfigFromFile = (filePath: string) => Promise<ConfigResult>;
|
||||
export type LoadConfigFromFile = (filePath: string) => AsyncResult<KubeConfig, ZodError<unknown>>;
|
||||
|
||||
const loadConfigFromFileInjectable = getInjectable({
|
||||
id: "load-config-from-file",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user