mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge remote-tracking branch 'origin/master' into monaco_editor_refactoring
# Conflicts: # src/common/user-store/preferences-helpers.ts # src/common/user-store/user-store.ts # src/renderer/bootstrap.tsx # src/renderer/components/+add-cluster/add-cluster.tsx # src/renderer/components/+apps-releases/release-details.tsx # src/renderer/components/+custom-resources/crd-details.tsx # src/renderer/components/+preferences/editor.tsx # src/renderer/components/+workloads-pods/pod-details-affinities.tsx # src/renderer/components/dock/create-resource.store.ts # src/renderer/components/dock/create-resource.tsx # src/renderer/components/dock/dock.store.ts # src/renderer/components/dock/edit-resource.store.ts # src/renderer/components/dock/editor-panel.tsx # src/renderer/components/dock/monaco-model-manager.ts # src/renderer/components/kubeconfig-dialog/kubeconfig-dialog.tsx
This commit is contained in:
commit
5f90caa112
51
.eslintrc.js
51
.eslintrc.js
@ -59,6 +59,11 @@ module.exports = {
|
|||||||
"SwitchCase": 1,
|
"SwitchCase": 1,
|
||||||
}],
|
}],
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
|
"space-before-function-paren": ["error", {
|
||||||
|
"anonymous": "always",
|
||||||
|
"named": "never",
|
||||||
|
"asyncArrow": "always",
|
||||||
|
}],
|
||||||
"unused-imports/no-unused-imports": "error",
|
"unused-imports/no-unused-imports": "error",
|
||||||
"unused-imports/no-unused-vars": [
|
"unused-imports/no-unused-vars": [
|
||||||
"warn", {
|
"warn", {
|
||||||
@ -71,12 +76,17 @@ module.exports = {
|
|||||||
"avoidEscape": true,
|
"avoidEscape": true,
|
||||||
"allowTemplateLiterals": true,
|
"allowTemplateLiterals": true,
|
||||||
}],
|
}],
|
||||||
|
"object-curly-spacing": ["error", "always", {
|
||||||
|
"objectsInObjects": false,
|
||||||
|
"arraysInObjects": true,
|
||||||
|
}],
|
||||||
"linebreak-style": ["error", "unix"],
|
"linebreak-style": ["error", "unix"],
|
||||||
"eol-last": ["error", "always"],
|
"eol-last": ["error", "always"],
|
||||||
"semi": ["error", "always"],
|
"semi": ["error", "always"],
|
||||||
"object-shorthand": "error",
|
"object-shorthand": "error",
|
||||||
"prefer-template": "error",
|
"prefer-template": "error",
|
||||||
"template-curly-spacing": "error",
|
"template-curly-spacing": "error",
|
||||||
|
"no-unused-expressions": "error",
|
||||||
"padding-line-between-statements": [
|
"padding-line-between-statements": [
|
||||||
"error",
|
"error",
|
||||||
{ "blankLine": "always", "prev": "*", "next": "return" },
|
{ "blankLine": "always", "prev": "*", "next": "return" },
|
||||||
@ -84,8 +94,9 @@ module.exports = {
|
|||||||
{ "blankLine": "always", "prev": "*", "next": "function" },
|
{ "blankLine": "always", "prev": "*", "next": "function" },
|
||||||
{ "blankLine": "always", "prev": "*", "next": "class" },
|
{ "blankLine": "always", "prev": "*", "next": "class" },
|
||||||
{ "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" },
|
{ "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" },
|
||||||
{ "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"]},
|
{ "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"] },
|
||||||
]
|
],
|
||||||
|
"no-template-curly-in-string": "error",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -115,6 +126,12 @@ module.exports = {
|
|||||||
"@typescript-eslint/ban-ts-comment": "off",
|
"@typescript-eslint/ban-ts-comment": "off",
|
||||||
"@typescript-eslint/no-empty-interface": "off",
|
"@typescript-eslint/no-empty-interface": "off",
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
|
"space-before-function-paren": "off",
|
||||||
|
"@typescript-eslint/space-before-function-paren": ["error", {
|
||||||
|
"anonymous": "always",
|
||||||
|
"named": "never",
|
||||||
|
"asyncArrow": "always",
|
||||||
|
}],
|
||||||
"unused-imports/no-unused-imports-ts": process.env.PROD === "true" ? "error" : "warn",
|
"unused-imports/no-unused-imports-ts": process.env.PROD === "true" ? "error" : "warn",
|
||||||
"unused-imports/no-unused-vars-ts": [
|
"unused-imports/no-unused-vars-ts": [
|
||||||
"warn", {
|
"warn", {
|
||||||
@ -130,6 +147,11 @@ module.exports = {
|
|||||||
"avoidEscape": true,
|
"avoidEscape": true,
|
||||||
"allowTemplateLiterals": true,
|
"allowTemplateLiterals": true,
|
||||||
}],
|
}],
|
||||||
|
"object-curly-spacing": "off",
|
||||||
|
"@typescript-eslint/object-curly-spacing": ["error", "always", {
|
||||||
|
"objectsInObjects": false,
|
||||||
|
"arraysInObjects": true,
|
||||||
|
}],
|
||||||
"react/prop-types": "off",
|
"react/prop-types": "off",
|
||||||
"semi": "off",
|
"semi": "off",
|
||||||
"@typescript-eslint/semi": ["error"],
|
"@typescript-eslint/semi": ["error"],
|
||||||
@ -138,6 +160,8 @@ module.exports = {
|
|||||||
"object-shorthand": "error",
|
"object-shorthand": "error",
|
||||||
"prefer-template": "error",
|
"prefer-template": "error",
|
||||||
"template-curly-spacing": "error",
|
"template-curly-spacing": "error",
|
||||||
|
"no-unused-expressions": "off",
|
||||||
|
"@typescript-eslint/no-unused-expressions": "error",
|
||||||
"padding-line-between-statements": [
|
"padding-line-between-statements": [
|
||||||
"error",
|
"error",
|
||||||
{ "blankLine": "always", "prev": "*", "next": "return" },
|
{ "blankLine": "always", "prev": "*", "next": "return" },
|
||||||
@ -145,8 +169,9 @@ module.exports = {
|
|||||||
{ "blankLine": "always", "prev": "*", "next": "function" },
|
{ "blankLine": "always", "prev": "*", "next": "function" },
|
||||||
{ "blankLine": "always", "prev": "*", "next": "class" },
|
{ "blankLine": "always", "prev": "*", "next": "class" },
|
||||||
{ "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" },
|
{ "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" },
|
||||||
{ "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"]},
|
{ "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"] },
|
||||||
]
|
],
|
||||||
|
"no-template-curly-in-string": "error",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -183,6 +208,12 @@ module.exports = {
|
|||||||
"@typescript-eslint/no-empty-function": "off",
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
"react/display-name": "off",
|
"react/display-name": "off",
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
"@typescript-eslint/no-unused-vars": "off",
|
||||||
|
"space-before-function-paren": "off",
|
||||||
|
"@typescript-eslint/space-before-function-paren": ["error", {
|
||||||
|
"anonymous": "always",
|
||||||
|
"named": "never",
|
||||||
|
"asyncArrow": "always",
|
||||||
|
}],
|
||||||
"unused-imports/no-unused-imports-ts": process.env.PROD === "true" ? "error" : "warn",
|
"unused-imports/no-unused-imports-ts": process.env.PROD === "true" ? "error" : "warn",
|
||||||
"unused-imports/no-unused-vars-ts": [
|
"unused-imports/no-unused-vars-ts": [
|
||||||
"warn", {
|
"warn", {
|
||||||
@ -198,6 +229,11 @@ module.exports = {
|
|||||||
"avoidEscape": true,
|
"avoidEscape": true,
|
||||||
"allowTemplateLiterals": true,
|
"allowTemplateLiterals": true,
|
||||||
}],
|
}],
|
||||||
|
"object-curly-spacing": "off",
|
||||||
|
"@typescript-eslint/object-curly-spacing": ["error", "always", {
|
||||||
|
"objectsInObjects": false,
|
||||||
|
"arraysInObjects": true,
|
||||||
|
}],
|
||||||
"react/prop-types": "off",
|
"react/prop-types": "off",
|
||||||
"semi": "off",
|
"semi": "off",
|
||||||
"@typescript-eslint/semi": ["error"],
|
"@typescript-eslint/semi": ["error"],
|
||||||
@ -206,6 +242,8 @@ module.exports = {
|
|||||||
"object-shorthand": "error",
|
"object-shorthand": "error",
|
||||||
"prefer-template": "error",
|
"prefer-template": "error",
|
||||||
"template-curly-spacing": "error",
|
"template-curly-spacing": "error",
|
||||||
|
"no-unused-expressions": "off",
|
||||||
|
"@typescript-eslint/no-unused-expressions": "error",
|
||||||
"padding-line-between-statements": [
|
"padding-line-between-statements": [
|
||||||
"error",
|
"error",
|
||||||
{ "blankLine": "always", "prev": "*", "next": "return" },
|
{ "blankLine": "always", "prev": "*", "next": "return" },
|
||||||
@ -213,10 +251,11 @@ module.exports = {
|
|||||||
{ "blankLine": "always", "prev": "*", "next": "function" },
|
{ "blankLine": "always", "prev": "*", "next": "function" },
|
||||||
{ "blankLine": "always", "prev": "*", "next": "class" },
|
{ "blankLine": "always", "prev": "*", "next": "class" },
|
||||||
{ "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" },
|
{ "blankLine": "always", "prev": ["const", "let", "var"], "next": "*" },
|
||||||
{ "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"]},
|
{ "blankLine": "any", "prev": ["const", "let", "var"], "next": ["const", "let", "var"] },
|
||||||
],
|
],
|
||||||
"react-hooks/rules-of-hooks": "error",
|
"react-hooks/rules-of-hooks": "error",
|
||||||
"react-hooks/exhaustive-deps": "off"
|
"react-hooks/exhaustive-deps": "off",
|
||||||
|
"no-template-curly-in-string": "error",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export default class ClusterMetricsFeatureExtension extends Renderer.LensExtensi
|
|||||||
title: "Lens Metrics",
|
title: "Lens Metrics",
|
||||||
priority: 5,
|
priority: 5,
|
||||||
components: {
|
components: {
|
||||||
View: ({ entity = null }: { entity: Common.Catalog.KubernetesCluster}) => {
|
View: ({ entity = null }: { entity: Common.Catalog.KubernetesCluster }) => {
|
||||||
return (
|
return (
|
||||||
<MetricsSettings cluster={entity} />
|
<MetricsSettings cluster={entity} />
|
||||||
);
|
);
|
||||||
|
|||||||
@ -92,11 +92,11 @@ export class MetricsFeature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async getStatus(): Promise<MetricsStatus> {
|
async getStatus(): Promise<MetricsStatus> {
|
||||||
const status: MetricsStatus = { installed: false, canUpgrade: false};
|
const status: MetricsStatus = { installed: false, canUpgrade: false };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const namespaceApi = forCluster(this.cluster, Namespace);
|
const namespaceApi = forCluster(this.cluster, Namespace);
|
||||||
const namespace = await namespaceApi.get({name: "lens-metrics"});
|
const namespace = await namespaceApi.get({ name: "lens-metrics" });
|
||||||
|
|
||||||
if (namespace?.kind) {
|
if (namespace?.kind) {
|
||||||
const currentVersion = namespace.metadata.annotations?.extensionVersion || "0.0.0";
|
const currentVersion = namespace.metadata.annotations?.extensionVersion || "0.0.0";
|
||||||
|
|||||||
@ -114,7 +114,7 @@ export class MetricsSettings extends React.Component<Props> {
|
|||||||
const statefulSet = forCluster(this.props.cluster, StatefulSet);
|
const statefulSet = forCluster(this.props.cluster, StatefulSet);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await statefulSet.get({name: "prometheus", namespace: "lens-metrics"});
|
await statefulSet.get({ name: "prometheus", namespace: "lens-metrics" });
|
||||||
this.featureStates.prometheus = true;
|
this.featureStates.prometheus = true;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (e?.error?.code === 404) {
|
if (e?.error?.code === 404) {
|
||||||
@ -127,7 +127,7 @@ export class MetricsSettings extends React.Component<Props> {
|
|||||||
const deployment = forCluster(this.props.cluster, Deployment);
|
const deployment = forCluster(this.props.cluster, Deployment);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await deployment.get({name: "kube-state-metrics", namespace: "lens-metrics"});
|
await deployment.get({ name: "kube-state-metrics", namespace: "lens-metrics" });
|
||||||
this.featureStates.kubeStateMetrics = true;
|
this.featureStates.kubeStateMetrics = true;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (e?.error?.code === 404) {
|
if (e?.error?.code === 404) {
|
||||||
@ -140,7 +140,7 @@ export class MetricsSettings extends React.Component<Props> {
|
|||||||
const daemonSet = forCluster(this.props.cluster, DaemonSet);
|
const daemonSet = forCluster(this.props.cluster, DaemonSet);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await daemonSet.get({name: "node-exporter", namespace: "lens-metrics"});
|
await daemonSet.get({ name: "node-exporter", namespace: "lens-metrics" });
|
||||||
this.featureStates.nodeExporter = true;
|
this.featureStates.nodeExporter = true;
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (e?.error?.code === 404) {
|
if (e?.error?.code === 404) {
|
||||||
@ -207,14 +207,14 @@ export class MetricsSettings extends React.Component<Props> {
|
|||||||
<>
|
<>
|
||||||
{ this.props.cluster.status.phase !== "connected" && (
|
{ this.props.cluster.status.phase !== "connected" && (
|
||||||
<section>
|
<section>
|
||||||
<p style={ {color: "var(--colorError)"} }>
|
<p style={ { color: "var(--colorError)" } }>
|
||||||
Lens Metrics settings requires established connection to the cluster.
|
Lens Metrics settings requires established connection to the cluster.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
{ !this.isActiveMetricsProvider && (
|
{ !this.isActiveMetricsProvider && (
|
||||||
<section>
|
<section>
|
||||||
<p style={ {color: "var(--colorError)"} }>
|
<p style={ { color: "var(--colorError)" } }>
|
||||||
Other metrics provider is currently active. See "Metrics" tab for details.
|
Other metrics provider is currently active. See "Metrics" tab for details.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -297,7 +297,7 @@
|
|||||||
"@types/request-promise-native": "^1.0.18",
|
"@types/request-promise-native": "^1.0.18",
|
||||||
"@types/semver": "^7.3.9",
|
"@types/semver": "^7.3.9",
|
||||||
"@types/sharp": "^0.29.2",
|
"@types/sharp": "^0.29.2",
|
||||||
"@types/spdy": "^3.4.4",
|
"@types/spdy": "^3.4.5",
|
||||||
"@types/tar": "^4.0.5",
|
"@types/tar": "^4.0.5",
|
||||||
"@types/tcp-port-used": "^1.0.0",
|
"@types/tcp-port-used": "^1.0.0",
|
||||||
"@types/tempy": "^0.3.0",
|
"@types/tempy": "^0.3.0",
|
||||||
@ -378,7 +378,7 @@
|
|||||||
"webpack-dev-server": "^3.11.2",
|
"webpack-dev-server": "^3.11.2",
|
||||||
"webpack-node-externals": "^1.7.2",
|
"webpack-node-externals": "^1.7.2",
|
||||||
"what-input": "^5.2.10",
|
"what-input": "^5.2.10",
|
||||||
"xterm": "^4.12.0",
|
"xterm": "^4.14.1",
|
||||||
"xterm-addon-fit": "^0.5.0"
|
"xterm-addon-fit": "^0.5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,7 @@ describe("event bus tests", () => {
|
|||||||
event = data;
|
event = data;
|
||||||
});
|
});
|
||||||
|
|
||||||
appEventBus.emit({name: "foo", action: "bar"});
|
appEventBus.emit({ name: "foo", action: "bar" });
|
||||||
expect(event.name).toBe("foo");
|
expect(event.name).toBe("foo");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -174,7 +174,7 @@ describe("kube helpers", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("multiple context is ok", async () => {
|
it("multiple context is ok", async () => {
|
||||||
mockKubeConfig.contexts.push({context: {cluster: "cluster-2", user: "cluster-2"}, name: "cluster-2"});
|
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "cluster-2" }, name: "cluster-2" });
|
||||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||||
|
|
||||||
expect(config.getCurrentContext()).toBe("minikube");
|
expect(config.getCurrentContext()).toBe("minikube");
|
||||||
@ -209,7 +209,7 @@ describe("kube helpers", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("empty name in context causes it to be removed", async () => {
|
it("empty name in context causes it to be removed", async () => {
|
||||||
mockKubeConfig.contexts.push({context: {cluster: "cluster-2", user: "cluster-2"}, name: ""});
|
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "cluster-2" }, name: "" });
|
||||||
expect(mockKubeConfig.contexts.length).toBe(2);
|
expect(mockKubeConfig.contexts.length).toBe(2);
|
||||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||||
|
|
||||||
@ -218,7 +218,7 @@ describe("kube helpers", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("empty cluster in context causes it to be removed", async () => {
|
it("empty cluster in context causes it to be removed", async () => {
|
||||||
mockKubeConfig.contexts.push({context: {cluster: "", user: "cluster-2"}, name: "cluster-2"});
|
mockKubeConfig.contexts.push({ context: { cluster: "", user: "cluster-2" }, name: "cluster-2" });
|
||||||
expect(mockKubeConfig.contexts.length).toBe(2);
|
expect(mockKubeConfig.contexts.length).toBe(2);
|
||||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||||
|
|
||||||
@ -227,7 +227,7 @@ describe("kube helpers", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("empty user in context causes it to be removed", async () => {
|
it("empty user in context causes it to be removed", async () => {
|
||||||
mockKubeConfig.contexts.push({context: {cluster: "cluster-2", user: ""}, name: "cluster-2"});
|
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "" }, name: "cluster-2" });
|
||||||
expect(mockKubeConfig.contexts.length).toBe(2);
|
expect(mockKubeConfig.contexts.length).toBe(2);
|
||||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||||
|
|
||||||
@ -236,8 +236,8 @@ describe("kube helpers", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("invalid context in between valid contexts is removed", async () => {
|
it("invalid context in between valid contexts is removed", async () => {
|
||||||
mockKubeConfig.contexts.push({context: {cluster: "cluster-2", user: ""}, name: "cluster-2"});
|
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "" }, name: "cluster-2" });
|
||||||
mockKubeConfig.contexts.push({context: {cluster: "cluster-3", user: "cluster-3"}, name: "cluster-3"});
|
mockKubeConfig.contexts.push({ context: { cluster: "cluster-3", user: "cluster-3" }, name: "cluster-3" });
|
||||||
expect(mockKubeConfig.contexts.length).toBe(3);
|
expect(mockKubeConfig.contexts.length).toBe(3);
|
||||||
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
|
||||||
|
|
||||||
|
|||||||
@ -52,7 +52,7 @@ AppPaths.init();
|
|||||||
describe("user store tests", () => {
|
describe("user store tests", () => {
|
||||||
describe("for an empty config", () => {
|
describe("for an empty config", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockFs({ tmp: { "config.json": "{}", "kube_config": "{}" } });
|
mockFs({ tmp: { "config.json": "{}", "kube_config": "{}" }});
|
||||||
|
|
||||||
(UserStore.createInstance() as any).refreshNewContexts = jest.fn(() => Promise.resolve());
|
(UserStore.createInstance() as any).refreshNewContexts = jest.fn(() => Promise.resolve());
|
||||||
});
|
});
|
||||||
|
|||||||
@ -32,11 +32,9 @@ import esbuild from "esbuild";
|
|||||||
const getTSLoader = (
|
const getTSLoader = (
|
||||||
testRegExp: RegExp, transpileOnly = true
|
testRegExp: RegExp, transpileOnly = true
|
||||||
) => {
|
) => {
|
||||||
const useEsbuildLoader = process.env.LENS_DEV_USE_ESBUILD_LOADER === "true";
|
if (process.env.LENS_DEV_USE_ESBUILD_LOADER === "true") {
|
||||||
|
console.info(`\n🚀 using esbuild-loader for ts(x)`);
|
||||||
|
|
||||||
useEsbuildLoader && console.info(`\n🚀 using esbuild-loader for ts(x)`);
|
|
||||||
|
|
||||||
if (useEsbuildLoader) {
|
|
||||||
return {
|
return {
|
||||||
test: testRegExp,
|
test: testRegExp,
|
||||||
loader: "esbuild-loader",
|
loader: "esbuild-loader",
|
||||||
|
|||||||
@ -73,8 +73,8 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
protected fromStore(data: Partial<HotbarStoreModel> = {}) {
|
protected fromStore(data: Partial<HotbarStoreModel> = {}) {
|
||||||
if (!data.hotbars || !data.hotbars.length) {
|
if (!data.hotbars || !data.hotbars.length) {
|
||||||
const hotbar = getEmptyHotbar("Default");
|
const hotbar = getEmptyHotbar("Default");
|
||||||
const { metadata: { uid, name, source } } = catalogEntity;
|
const { metadata: { uid, name, source }} = catalogEntity;
|
||||||
const initialItem = { entity: { uid, name, source } };
|
const initialItem = { entity: { uid, name, source }};
|
||||||
|
|
||||||
hotbar.items[0] = initialItem;
|
hotbar.items[0] = initialItem;
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ describe("DeploymentApi", () => {
|
|||||||
it("requests Kubernetes API with PATCH verb and correct amount of replicas", () => {
|
it("requests Kubernetes API with PATCH verb and correct amount of replicas", () => {
|
||||||
const patchSpy = jest.spyOn(requestMock, "patch");
|
const patchSpy = jest.spyOn(requestMock, "patch");
|
||||||
|
|
||||||
sub.scale({ namespace: "default", name: "deployment-1"}, 5);
|
sub.scale({ namespace: "default", name: "deployment-1" }, 5);
|
||||||
|
|
||||||
expect(patchSpy).toHaveBeenCalledWith("/apis/apps/v1/namespaces/default/deployments/deployment-1/scale", {
|
expect(patchSpy).toHaveBeenCalledWith("/apis/apps/v1/namespaces/default/deployments/deployment-1/scale", {
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@ -45,12 +45,12 @@ describe("KubeObject", () => {
|
|||||||
{
|
{
|
||||||
type TestCase = [string, any];
|
type TestCase = [string, any];
|
||||||
const tests: TestCase[] = [
|
const tests: TestCase[] = [
|
||||||
["kind", { apiVersion: "", metadata: {uid: "", name: "", resourceVersion: "", selfLink: ""} }],
|
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||||
["apiVersion", { kind: "", metadata: {uid: "", name: "", resourceVersion: "", selfLink: ""} }],
|
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||||
["metadata", { kind: "", apiVersion: "" }],
|
["metadata", { kind: "", apiVersion: "" }],
|
||||||
["metadata.uid", { kind: "", apiVersion: "", metadata: { name: "", resourceVersion: "", selfLink: ""} }],
|
["metadata.uid", { kind: "", apiVersion: "", metadata: { name: "", resourceVersion: "", selfLink: "" }}],
|
||||||
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", resourceVersion: "", selfLink: "" } }],
|
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", resourceVersion: "", selfLink: "" }}],
|
||||||
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", selfLink: "" } }],
|
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", selfLink: "" }}],
|
||||||
];
|
];
|
||||||
|
|
||||||
it.each(tests)("should reject with missing: %s", (missingField, input) => {
|
it.each(tests)("should reject with missing: %s", (missingField, input) => {
|
||||||
@ -61,23 +61,23 @@ describe("KubeObject", () => {
|
|||||||
{
|
{
|
||||||
type TestCase = [string, any];
|
type TestCase = [string, any];
|
||||||
const tests: TestCase[] = [
|
const tests: TestCase[] = [
|
||||||
["kind", { kind: 1, apiVersion: "", metadata: {} }],
|
["kind", { kind: 1, apiVersion: "", metadata: {}}],
|
||||||
["apiVersion", { apiVersion: 1, kind: "", metadata: {} }],
|
["apiVersion", { apiVersion: 1, kind: "", metadata: {}}],
|
||||||
["metadata", { kind: "", apiVersion: "", metadata: "" }],
|
["metadata", { kind: "", apiVersion: "", metadata: "" }],
|
||||||
["metadata.uid", { kind: "", apiVersion: "", metadata: { uid: 1 } }],
|
["metadata.uid", { kind: "", apiVersion: "", metadata: { uid: 1 }}],
|
||||||
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", name: 1 } }],
|
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", name: 1 }}],
|
||||||
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: 1 } }],
|
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: 1 }}],
|
||||||
["metadata.selfLink", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: 1 } }],
|
["metadata.selfLink", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: 1 }}],
|
||||||
["metadata.namespace", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", namespace: 1 } }],
|
["metadata.namespace", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", namespace: 1 }}],
|
||||||
["metadata.creationTimestamp", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", creationTimestamp: 1 } }],
|
["metadata.creationTimestamp", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", creationTimestamp: 1 }}],
|
||||||
["metadata.continue", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", continue: 1 } }],
|
["metadata.continue", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", continue: 1 }}],
|
||||||
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: 1 } }],
|
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: 1 }}],
|
||||||
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: [1] } }],
|
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: [1] }}],
|
||||||
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: {} } }],
|
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: {}}}],
|
||||||
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: 1 } }],
|
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: 1 }}],
|
||||||
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: { food: 1 } } }],
|
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: { food: 1 }}}],
|
||||||
["metadata.annotations", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: 1 } }],
|
["metadata.annotations", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: 1 }}],
|
||||||
["metadata.annotations", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: 1 } } }],
|
["metadata.annotations", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: 1 }}}],
|
||||||
];
|
];
|
||||||
|
|
||||||
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
|
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
|
||||||
@ -86,7 +86,7 @@ describe("KubeObject", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it("should accept valid KubeJsonApiData (ignoring other fields)", () => {
|
it("should accept valid KubeJsonApiData (ignoring other fields)", () => {
|
||||||
const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" } } };
|
const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" }}};
|
||||||
|
|
||||||
expect(KubeObject.isJsonApiData(valid)).toBe(true);
|
expect(KubeObject.isJsonApiData(valid)).toBe(true);
|
||||||
});
|
});
|
||||||
@ -118,8 +118,8 @@ describe("KubeObject", () => {
|
|||||||
{
|
{
|
||||||
type TestCase = [string, any];
|
type TestCase = [string, any];
|
||||||
const tests: TestCase[] = [
|
const tests: TestCase[] = [
|
||||||
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" } }],
|
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||||
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" } }],
|
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||||
["metadata", { kind: "", apiVersion: "" }],
|
["metadata", { kind: "", apiVersion: "" }],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -131,23 +131,23 @@ describe("KubeObject", () => {
|
|||||||
{
|
{
|
||||||
type TestCase = [string, any];
|
type TestCase = [string, any];
|
||||||
const tests: TestCase[] = [
|
const tests: TestCase[] = [
|
||||||
["kind", { kind: 1, apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" } }],
|
["kind", { kind: 1, apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||||
["apiVersion", { apiVersion: 1, kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" } }],
|
["apiVersion", { apiVersion: 1, kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
|
||||||
["metadata", { kind: "", apiVersion: "", metadata: "" }],
|
["metadata", { kind: "", apiVersion: "", metadata: "" }],
|
||||||
["metadata.uid", { kind: "", apiVersion: "", metadata: { uid: 1, name: "", resourceVersion: "", selfLink: "" } }],
|
["metadata.uid", { kind: "", apiVersion: "", metadata: { uid: 1, name: "", resourceVersion: "", selfLink: "" }}],
|
||||||
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", name: 1, resourceVersion: "", selfLink: "" } }],
|
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", name: 1, resourceVersion: "", selfLink: "" }}],
|
||||||
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: 1, selfLink: "" } }],
|
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: 1, selfLink: "" }}],
|
||||||
["metadata.selfLink", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: 1 } }],
|
["metadata.selfLink", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: 1 }}],
|
||||||
["metadata.namespace", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", namespace: 1 } }],
|
["metadata.namespace", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", namespace: 1 }}],
|
||||||
["metadata.creationTimestamp", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", creationTimestamp: 1 } }],
|
["metadata.creationTimestamp", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", creationTimestamp: 1 }}],
|
||||||
["metadata.continue", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", continue: 1 } }],
|
["metadata.continue", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", continue: 1 }}],
|
||||||
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: 1 } }],
|
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: 1 }}],
|
||||||
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: [1] } }],
|
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: [1] }}],
|
||||||
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: {} } }],
|
["metadata.finalizers", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", finalizers: {}}}],
|
||||||
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: 1 } }],
|
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: 1 }}],
|
||||||
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: { food: 1 } } }],
|
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: { food: 1 }}}],
|
||||||
["metadata.annotations", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: 1 } }],
|
["metadata.annotations", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: 1 }}],
|
||||||
["metadata.annotations", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: 1 } } }],
|
["metadata.annotations", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: 1 }}}],
|
||||||
];
|
];
|
||||||
|
|
||||||
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
|
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
|
||||||
@ -156,7 +156,7 @@ describe("KubeObject", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it("should accept valid Partial<KubeJsonApiData> (ignoring other fields)", () => {
|
it("should accept valid Partial<KubeJsonApiData> (ignoring other fields)", () => {
|
||||||
const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" } } };
|
const valid = { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", annotations: { food: "" }}};
|
||||||
|
|
||||||
expect(KubeObject.isPartialJsonApiData(valid)).toBe(true);
|
expect(KubeObject.isPartialJsonApiData(valid)).toBe(true);
|
||||||
});
|
});
|
||||||
@ -197,8 +197,8 @@ describe("KubeObject", () => {
|
|||||||
{
|
{
|
||||||
type TestCase = [string, any];
|
type TestCase = [string, any];
|
||||||
const tests: TestCase[] = [
|
const tests: TestCase[] = [
|
||||||
["kind", { apiVersion: "", items: [], metadata: { resourceVersion: "", selfLink: "" } }],
|
["kind", { apiVersion: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}],
|
||||||
["apiVersion", { kind: "", items: [], metadata: { resourceVersion: "", selfLink: "" } }],
|
["apiVersion", { kind: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}],
|
||||||
["metadata", { kind: "", items: [], apiVersion: "" }],
|
["metadata", { kind: "", items: [], apiVersion: "" }],
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -210,15 +210,15 @@ describe("KubeObject", () => {
|
|||||||
{
|
{
|
||||||
type TestCase = [string, any];
|
type TestCase = [string, any];
|
||||||
const tests: TestCase[] = [
|
const tests: TestCase[] = [
|
||||||
["kind", { kind: 1, items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" } }],
|
["kind", { kind: 1, items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}],
|
||||||
["apiVersion", { kind: "", items: [], apiVersion: 1, metadata: { resourceVersion: "", selfLink: "" } }],
|
["apiVersion", { kind: "", items: [], apiVersion: 1, metadata: { resourceVersion: "", selfLink: "" }}],
|
||||||
["metadata", { kind: "", items: [], apiVersion: "", metadata: 1 }],
|
["metadata", { kind: "", items: [], apiVersion: "", metadata: 1 }],
|
||||||
["metadata.resourceVersion", { kind: "", items: [], apiVersion: "", metadata: { resourceVersion: 1, selfLink: "" } }],
|
["metadata.resourceVersion", { kind: "", items: [], apiVersion: "", metadata: { resourceVersion: 1, selfLink: "" }}],
|
||||||
["metadata.selfLink", { kind: "", items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: 1 } }],
|
["metadata.selfLink", { kind: "", items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: 1 }}],
|
||||||
["items", { kind: "", items: 1, apiVersion: "", metadata: { resourceVersion: "", selfLink: "" } }],
|
["items", { kind: "", items: 1, apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}],
|
||||||
["items", { kind: "", items: "", apiVersion: "", metadata: { resourceVersion: "", selfLink: "" } }],
|
["items", { kind: "", items: "", apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}],
|
||||||
["items", { kind: "", items: {}, apiVersion: "", metadata: { resourceVersion: "", selfLink: "" } }],
|
["items", { kind: "", items: {}, apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}],
|
||||||
["items[0]", { kind: "", items: [""], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" } }],
|
["items[0]", { kind: "", items: [""], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}],
|
||||||
];
|
];
|
||||||
|
|
||||||
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
|
it.each(tests)("should reject with wrong type for field: %s", (missingField, input) => {
|
||||||
@ -227,7 +227,7 @@ describe("KubeObject", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
it("should accept valid KubeJsonApiDataList (ignoring other fields)", () => {
|
it("should accept valid KubeJsonApiDataList (ignoring other fields)", () => {
|
||||||
const valid = { kind: "", items: [false], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" } };
|
const valid = { kind: "", items: [false], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }};
|
||||||
|
|
||||||
expect(KubeObject.isJsonApiDataList(valid, isBoolean)).toBe(true);
|
expect(KubeObject.isJsonApiDataList(valid, isBoolean)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -41,7 +41,7 @@ describe("StatefulSetApi", () => {
|
|||||||
it("requests Kubernetes API with PATCH verb and correct amount of replicas", () => {
|
it("requests Kubernetes API with PATCH verb and correct amount of replicas", () => {
|
||||||
const patchSpy = jest.spyOn(requestMock, "patch");
|
const patchSpy = jest.spyOn(requestMock, "patch");
|
||||||
|
|
||||||
sub.scale({ namespace: "default", name: "statefulset-1"}, 5);
|
sub.scale({ namespace: "default", name: "statefulset-1" }, 5);
|
||||||
|
|
||||||
expect(patchSpy).toHaveBeenCalledWith("/apis/apps/v1/namespaces/default/statefulsets/statefulset-1/scale", {
|
expect(patchSpy).toHaveBeenCalledWith("/apis/apps/v1/namespaces/default/statefulsets/statefulset-1/scale", {
|
||||||
data: {
|
data: {
|
||||||
|
|||||||
@ -163,7 +163,7 @@ export class CustomResourceDefinition extends KubeObject {
|
|||||||
}
|
}
|
||||||
} else if (this.spec.version) {
|
} else if (this.spec.version) {
|
||||||
const { additionalPrinterColumns: apc } = this.spec;
|
const { additionalPrinterColumns: apc } = this.spec;
|
||||||
const additionalPrinterColumns = apc?.map(({ JSONPath, ...apc}) => ({ ...apc, jsonPath: JSONPath }));
|
const additionalPrinterColumns = apc?.map(({ JSONPath, ...apc }) => ({ ...apc, jsonPath: JSONPath }));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: this.spec.version,
|
name: this.spec.version,
|
||||||
|
|||||||
@ -61,7 +61,7 @@ export class DeploymentApi extends KubeApi<Deployment> {
|
|||||||
spec: {
|
spec: {
|
||||||
template: {
|
template: {
|
||||||
metadata: {
|
metadata: {
|
||||||
annotations: {"kubectl.kubernetes.io/restartedAt" : moment.utc().format()}
|
annotations: { "kubectl.kubernetes.io/restartedAt" : moment.utc().format() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +122,7 @@ export class Deployment extends WorkloadKubeObject {
|
|||||||
|
|
||||||
declare spec: {
|
declare spec: {
|
||||||
replicas: number;
|
replicas: number;
|
||||||
selector: { matchLabels: { [app: string]: string } };
|
selector: { matchLabels: { [app: string]: string }};
|
||||||
template: {
|
template: {
|
||||||
metadata: {
|
metadata: {
|
||||||
creationTimestamp?: string;
|
creationTimestamp?: string;
|
||||||
|
|||||||
@ -83,7 +83,7 @@ export class EndpointAddress implements IEndpointAddress {
|
|||||||
|
|
||||||
getTargetRef(): ITargetRef {
|
getTargetRef(): ITargetRef {
|
||||||
if (this.targetRef) {
|
if (this.targetRef) {
|
||||||
return Object.assign(this.targetRef, {apiVersion: "v1"});
|
return Object.assign(this.targetRef, { apiVersion: "v1" });
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,7 +128,7 @@ export class Ingress extends KubeObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRoutes() {
|
getRoutes() {
|
||||||
const { spec: { tls, rules } } = this;
|
const { spec: { tls, rules }} = this;
|
||||||
|
|
||||||
if (!rules) return [];
|
if (!rules) return [];
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ export class Ingress extends KubeObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getHosts() {
|
getHosts() {
|
||||||
const { spec: { rules } } = this;
|
const { spec: { rules }} = this;
|
||||||
|
|
||||||
if (!rules) return [];
|
if (!rules) return [];
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ export class Ingress extends KubeObject {
|
|||||||
|
|
||||||
getPorts() {
|
getPorts() {
|
||||||
const ports: number[] = [];
|
const ports: number[] = [];
|
||||||
const { spec: { tls, rules, backend, defaultBackend } } = this;
|
const { spec: { tls, rules, backend, defaultBackend }} = this;
|
||||||
const httpPort = 80;
|
const httpPort = 80;
|
||||||
const tlsPort = 443;
|
const tlsPort = 443;
|
||||||
// Note: not using the port name (string)
|
// Note: not using the port name (string)
|
||||||
@ -196,7 +196,7 @@ export class Ingress extends KubeObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getLoadBalancers() {
|
getLoadBalancers() {
|
||||||
const { status: { loadBalancer = { ingress: [] } } } = this;
|
const { status: { loadBalancer = { ingress: [] }}} = this;
|
||||||
|
|
||||||
return (loadBalancer.ingress ?? []).map(address => (
|
return (loadBalancer.ingress ?? []).map(address => (
|
||||||
address.hostname || address.ip
|
address.hostname || address.ip
|
||||||
|
|||||||
@ -30,7 +30,7 @@ export class NodesApi extends KubeApi<Node> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getMetricsForAllNodes(): Promise<INodeMetrics> {
|
export function getMetricsForAllNodes(): Promise<INodeMetrics> {
|
||||||
const opts = { category: "nodes"};
|
const opts = { category: "nodes" };
|
||||||
|
|
||||||
return metricsApi.getMetrics({
|
return metricsApi.getMetrics({
|
||||||
memoryUsage: opts,
|
memoryUsage: opts,
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export interface PodDisruptionBudget {
|
|||||||
spec: {
|
spec: {
|
||||||
minAvailable: string;
|
minAvailable: string;
|
||||||
maxUnavailable: string;
|
maxUnavailable: string;
|
||||||
selector: { matchLabels: { [app: string]: string } };
|
selector: { matchLabels: { [app: string]: string }};
|
||||||
};
|
};
|
||||||
status: {
|
status: {
|
||||||
currentHealthy: number
|
currentHealthy: number
|
||||||
|
|||||||
@ -411,7 +411,7 @@ export class Pod extends WorkloadKubeObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getNodeSelectors(): string[] {
|
getNodeSelectors(): string[] {
|
||||||
const { nodeSelector = {} } = this.spec;
|
const { nodeSelector = {}} = this.spec;
|
||||||
|
|
||||||
return Object.entries(nodeSelector).map(values => values.join(": "));
|
return Object.entries(nodeSelector).map(values => values.join(": "));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export class ReplicaSet extends WorkloadKubeObject {
|
|||||||
|
|
||||||
declare spec: {
|
declare spec: {
|
||||||
replicas?: number;
|
replicas?: number;
|
||||||
selector: { matchLabels: { [app: string]: string } };
|
selector: { matchLabels: { [app: string]: string }};
|
||||||
template?: {
|
template?: {
|
||||||
metadata: {
|
metadata: {
|
||||||
labels: {
|
labels: {
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export interface Service {
|
|||||||
clusterIP: string;
|
clusterIP: string;
|
||||||
clusterIPs?: string[];
|
clusterIPs?: string[];
|
||||||
externalTrafficPolicy?: string;
|
externalTrafficPolicy?: string;
|
||||||
externalName: string;
|
externalName?: string;
|
||||||
loadBalancerIP?: string;
|
loadBalancerIP?: string;
|
||||||
loadBalancerSourceRanges?: string[];
|
loadBalancerSourceRanges?: string[];
|
||||||
sessionAffinity: string;
|
sessionAffinity: string;
|
||||||
@ -100,11 +100,15 @@ export class Service extends KubeObject {
|
|||||||
getExternalIps() {
|
getExternalIps() {
|
||||||
const lb = this.getLoadBalancer();
|
const lb = this.getLoadBalancer();
|
||||||
|
|
||||||
if (lb && lb.ingress) {
|
if (lb?.ingress) {
|
||||||
return lb.ingress.map(val => val.ip || val.hostname);
|
return lb.ingress.map(val => val.ip || val.hostname);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.spec.externalIPs || [];
|
if (Array.isArray(this.spec?.externalIPs)) {
|
||||||
|
return this.spec.externalIPs;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
getType() {
|
getType() {
|
||||||
|
|||||||
@ -376,8 +376,8 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
timedRetry = setTimeout(() => {
|
timedRetry = setTimeout(() => {
|
||||||
(
|
(
|
||||||
namespace
|
namespace
|
||||||
? this.loadAll({ namespaces: [namespace], reqInit: { signal } })
|
? this.loadAll({ namespaces: [namespace], reqInit: { signal }})
|
||||||
: this.loadAll({ merge: false, reqInit: { signal } })
|
: this.loadAll({ merge: false, reqInit: { signal }})
|
||||||
).then(watch);
|
).then(watch);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
} else if (error) { // not sure what to do, best to retry
|
} else if (error) { // not sure what to do, best to retry
|
||||||
|
|||||||
@ -134,7 +134,7 @@ export class KubeWatchApi {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected log({ message, cssStyle = "", meta = {} }: IKubeWatchLog) {
|
protected log({ message, cssStyle = "", meta = {}}: IKubeWatchLog) {
|
||||||
if (isProduction && !isDebugging) {
|
if (isProduction && !isDebugging) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {boundMethod, boundClass} from "autobind-decorator";
|
import { boundMethod, boundClass } from "autobind-decorator";
|
||||||
import autoBindClass, { Options } from "auto-bind";
|
import autoBindClass, { Options } from "auto-bind";
|
||||||
import autoBindReactClass from "auto-bind/react";
|
import autoBindReactClass from "auto-bind/react";
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export function buildURL<P extends object = {}, Q extends object = {}>(path: str
|
|||||||
export function buildURLPositional<P extends object = {}, Q extends object = {}>(path: string | any) {
|
export function buildURLPositional<P extends object = {}, Q extends object = {}>(path: string | any) {
|
||||||
const builder = buildURL(path);
|
const builder = buildURL(path);
|
||||||
|
|
||||||
return function(params?: P, query?: Q, fragment?: string): string {
|
return function (params?: P, query?: Q, fragment?: string): string {
|
||||||
return builder({ params, query, fragment });
|
return builder({ params, query, fragment });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ describe("extension compatibility", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("has no extension comparator", () => {
|
it("has no extension comparator", () => {
|
||||||
const manifest = { name: "extensionName", version: "0.0.1"};
|
const manifest = { name: "extensionName", version: "0.0.1" };
|
||||||
|
|
||||||
expect(isCompatibleExtension(manifest,)).toBe(false);
|
expect(isCompatibleExtension(manifest,)).toBe(false);
|
||||||
});
|
});
|
||||||
@ -76,7 +76,7 @@ describe("extension compatibility", () => {
|
|||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
])("extension comparator test: %p", ({ comparator, expected }) => {
|
])("extension comparator test: %p", ({ comparator, expected }) => {
|
||||||
const manifest: LensExtensionManifest = { name: "extensionName", version: "0.0.1", engines: { lens: comparator}};
|
const manifest: LensExtensionManifest = { name: "extensionName", version: "0.0.1", engines: { lens: comparator }};
|
||||||
|
|
||||||
expect(isCompatibleExtension(manifest,)).toBe(expected);
|
expect(isCompatibleExtension(manifest,)).toBe(expected);
|
||||||
});
|
});
|
||||||
@ -91,7 +91,7 @@ describe("extension compatibility", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("has no extension comparator", () => {
|
it("has no extension comparator", () => {
|
||||||
const manifest = { name: "extensionName", version: "0.0.1"};
|
const manifest = { name: "extensionName", version: "0.0.1" };
|
||||||
|
|
||||||
expect(isCompatibleExtension(manifest,)).toBe(false);
|
expect(isCompatibleExtension(manifest,)).toBe(false);
|
||||||
});
|
});
|
||||||
@ -130,7 +130,7 @@ describe("extension compatibility", () => {
|
|||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
])("extension comparator test: %p", ({ comparator, expected }) => {
|
])("extension comparator test: %p", ({ comparator, expected }) => {
|
||||||
const manifest: LensExtensionManifest = { name: "extensionName", version: "0.0.1", engines: { lens: comparator}};
|
const manifest: LensExtensionManifest = { name: "extensionName", version: "0.0.1", engines: { lens: comparator }};
|
||||||
|
|
||||||
expect(isCompatibleExtension(manifest,)).toBe(expected);
|
expect(isCompatibleExtension(manifest,)).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -45,8 +45,8 @@ export class ExtensionsStore extends BaseStore<LensExtensionsStoreModel> {
|
|||||||
@computed
|
@computed
|
||||||
get enabledExtensions() {
|
get enabledExtensions() {
|
||||||
return Array.from(this.state.values())
|
return Array.from(this.state.values())
|
||||||
.filter(({enabled}) => enabled)
|
.filter(({ enabled }) => enabled)
|
||||||
.map(({name}) => name);
|
.map(({ name }) => name);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected state = observable.map<LensExtensionId, LensExtensionState>();
|
protected state = observable.map<LensExtensionId, LensExtensionState>();
|
||||||
|
|||||||
@ -44,12 +44,12 @@ export abstract class IpcMain extends IpcRegistrar {
|
|||||||
listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
|
listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
|
||||||
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
|
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
|
||||||
const cleanup = once(() => {
|
const cleanup = once(() => {
|
||||||
logger.info(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version } });
|
logger.info(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
|
||||||
|
|
||||||
return ipcMain.removeListener(prefixedChannel, listener);
|
return ipcMain.removeListener(prefixedChannel, listener);
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.info(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version } });
|
logger.info(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
|
||||||
ipcMain.addListener(prefixedChannel, listener);
|
ipcMain.addListener(prefixedChannel, listener);
|
||||||
this.extension[Disposers].push(cleanup);
|
this.extension[Disposers].push(cleanup);
|
||||||
|
|
||||||
@ -64,10 +64,10 @@ export abstract class IpcMain extends IpcRegistrar {
|
|||||||
handle(channel: string, handler: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any): void {
|
handle(channel: string, handler: (event: Electron.IpcMainInvokeEvent, ...args: any[]) => any): void {
|
||||||
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
|
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
|
||||||
|
|
||||||
logger.info(`[IPC-RENDERER]: adding extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version } });
|
logger.info(`[IPC-RENDERER]: adding extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
|
||||||
ipcMainHandle(prefixedChannel, handler);
|
ipcMainHandle(prefixedChannel, handler);
|
||||||
this.extension[Disposers].push(() => {
|
this.extension[Disposers].push(() => {
|
||||||
logger.info(`[IPC-RENDERER]: removing extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version } });
|
logger.info(`[IPC-RENDERER]: removing extension handler`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
|
||||||
|
|
||||||
return ipcMain.removeHandler(prefixedChannel);
|
return ipcMain.removeHandler(prefixedChannel);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -44,12 +44,12 @@ export abstract class IpcRenderer extends IpcRegistrar {
|
|||||||
listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
|
listen(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => any): Disposer {
|
||||||
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
|
const prefixedChannel = `extensions@${this[IpcPrefix]}:${channel}`;
|
||||||
const cleanup = once(() => {
|
const cleanup = once(() => {
|
||||||
console.info(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version } });
|
console.info(`[IPC-RENDERER]: removing extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
|
||||||
|
|
||||||
return ipcRenderer.removeListener(prefixedChannel, listener);
|
return ipcRenderer.removeListener(prefixedChannel, listener);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.info(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version } });
|
console.info(`[IPC-RENDERER]: adding extension listener`, { channel, extension: { name: this.extension.name, version: this.extension.version }});
|
||||||
ipcRenderer.addListener(prefixedChannel, listener);
|
ipcRenderer.addListener(prefixedChannel, listener);
|
||||||
this.extension[Disposers].push(cleanup);
|
this.extension[Disposers].push(cleanup);
|
||||||
|
|
||||||
|
|||||||
@ -66,7 +66,7 @@ export interface RegisteredPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getExtensionPageUrl(target: PageTarget): string {
|
export function getExtensionPageUrl(target: PageTarget): string {
|
||||||
const { extensionId, pageId = "", params: targetParams = {} } = target;
|
const { extensionId, pageId = "", params: targetParams = {}} = target;
|
||||||
|
|
||||||
const pagePath = ["/extension", sanitizeExtensionName(extensionId), pageId]
|
const pagePath = ["/extension", sanitizeExtensionName(extensionId), pageId]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
|
|||||||
@ -212,7 +212,7 @@ export function computeDiff(contents: string, source: RootSource, filePath: stri
|
|||||||
// add new clusters to the source
|
// add new clusters to the source
|
||||||
try {
|
try {
|
||||||
const clusterId = createHash("md5").update(`${filePath}:${contextName}`).digest("hex");
|
const clusterId = createHash("md5").update(`${filePath}:${contextName}`).digest("hex");
|
||||||
const cluster = ClusterStore.getInstance().getById(clusterId) || new Cluster({ ...model, id: clusterId});
|
const cluster = ClusterStore.getInstance().getById(clusterId) || new Cluster({ ...model, id: clusterId });
|
||||||
|
|
||||||
if (!cluster.apiUrl) {
|
if (!cluster.apiUrl) {
|
||||||
throw new Error("Cluster constructor failed, see above error");
|
throw new Error("Cluster constructor failed, see above error");
|
||||||
|
|||||||
@ -100,7 +100,7 @@ export function syncWeblinks() {
|
|||||||
webLinkEntities.delete(weblinkId);
|
webLinkEntities.delete(weblinkId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {fireImmediately: true});
|
}, { fireImmediately: true });
|
||||||
|
|
||||||
catalogEntityRegistry.addComputedSource("weblinks", computed(() => Array.from(webLinkEntities.values(), ([link]) => link)));
|
catalogEntityRegistry.addComputedSource("weblinks", computed(() => Array.from(webLinkEntities.values(), ([link]) => link)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export class DetectorRegistry extends Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async detectForCluster(cluster: Cluster): Promise<ClusterMetadata> {
|
async detectForCluster(cluster: Cluster): Promise<ClusterMetadata> {
|
||||||
const results: {[key: string]: ClusterDetectionResult } = {};
|
const results: { [key: string]: ClusterDetectionResult } = {};
|
||||||
|
|
||||||
for (const detectorClass of this.registry) {
|
for (const detectorClass of this.registry) {
|
||||||
const detector = new detectorClass(cluster);
|
const detector = new detectorClass(cluster);
|
||||||
|
|||||||
@ -30,86 +30,86 @@ export class DistributionDetector extends BaseClusterDetector {
|
|||||||
this.version = await this.getKubernetesVersion();
|
this.version = await this.getKubernetesVersion();
|
||||||
|
|
||||||
if (this.isRke()) {
|
if (this.isRke()) {
|
||||||
return { value: "rke", accuracy: 80};
|
return { value: "rke", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isRancherDesktop()) {
|
if (this.isRancherDesktop()) {
|
||||||
return { value: "rancher-desktop", accuracy: 80};
|
return { value: "rancher-desktop", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isK3s()) {
|
if (this.isK3s()) {
|
||||||
return { value: "k3s", accuracy: 80};
|
return { value: "k3s", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isGKE()) {
|
if (this.isGKE()) {
|
||||||
return { value: "gke", accuracy: 80};
|
return { value: "gke", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isEKS()) {
|
if (this.isEKS()) {
|
||||||
return { value: "eks", accuracy: 80};
|
return { value: "eks", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isIKS()) {
|
if (this.isIKS()) {
|
||||||
return { value: "iks", accuracy: 80};
|
return { value: "iks", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isAKS()) {
|
if (this.isAKS()) {
|
||||||
return { value: "aks", accuracy: 80};
|
return { value: "aks", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isDigitalOcean()) {
|
if (this.isDigitalOcean()) {
|
||||||
return { value: "digitalocean", accuracy: 90};
|
return { value: "digitalocean", accuracy: 90 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isK0s()) {
|
if (this.isK0s()) {
|
||||||
return { value: "k0s", accuracy: 80};
|
return { value: "k0s", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isVMWare()) {
|
if (this.isVMWare()) {
|
||||||
return { value: "vmware", accuracy: 90};
|
return { value: "vmware", accuracy: 90 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isMirantis()) {
|
if (this.isMirantis()) {
|
||||||
return { value: "mirantis", accuracy: 90};
|
return { value: "mirantis", accuracy: 90 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isAlibaba()) {
|
if (this.isAlibaba()) {
|
||||||
return { value: "alibaba", accuracy: 90};
|
return { value: "alibaba", accuracy: 90 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isHuawei()) {
|
if (this.isHuawei()) {
|
||||||
return { value: "huawei", accuracy: 90};
|
return { value: "huawei", accuracy: 90 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isTke()) {
|
if (this.isTke()) {
|
||||||
return { value: "tencent", accuracy: 90};
|
return { value: "tencent", accuracy: 90 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isMinikube()) {
|
if (this.isMinikube()) {
|
||||||
return { value: "minikube", accuracy: 80};
|
return { value: "minikube", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isMicrok8s()) {
|
if (this.isMicrok8s()) {
|
||||||
return { value: "microk8s", accuracy: 80};
|
return { value: "microk8s", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isKind()) {
|
if (this.isKind()) {
|
||||||
return { value: "kind", accuracy: 70};
|
return { value: "kind", accuracy: 70 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isDockerDesktop()) {
|
if (this.isDockerDesktop()) {
|
||||||
return { value: "docker-desktop", accuracy: 80};
|
return { value: "docker-desktop", accuracy: 80 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isCustom() && await this.isOpenshift()) {
|
if (this.isCustom() && await this.isOpenshift()) {
|
||||||
return { value: "openshift", accuracy: 90};
|
return { value: "openshift", accuracy: 90 };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isCustom()) {
|
if (this.isCustom()) {
|
||||||
return { value: "custom", accuracy: 10};
|
return { value: "custom", accuracy: 10 };
|
||||||
}
|
}
|
||||||
|
|
||||||
return { value: "unknown", accuracy: 10};
|
return { value: "unknown", accuracy: 10 };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getKubernetesVersion() {
|
public async getKubernetesVersion() {
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export class NodesCountDetector extends BaseClusterDetector {
|
|||||||
if (!this.cluster.accessible) return null;
|
if (!this.cluster.accessible) return null;
|
||||||
const nodeCount = await this.getNodeCount();
|
const nodeCount = await this.getNodeCount();
|
||||||
|
|
||||||
return { value: nodeCount, accuracy: 100};
|
return { value: nodeCount, accuracy: 100 };
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getNodeCount(): Promise<number> {
|
protected async getNodeCount(): Promise<number> {
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export class VersionDetector extends BaseClusterDetector {
|
|||||||
public async detect() {
|
public async detect() {
|
||||||
const version = await this.getKubernetesVersion();
|
const version = await this.getKubernetesVersion();
|
||||||
|
|
||||||
return { value: version, accuracy: 100};
|
return { value: version, accuracy: 100 };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getKubernetesVersion() {
|
public async getKubernetesVersion() {
|
||||||
|
|||||||
@ -651,7 +651,7 @@ export class Cluster implements ClusterModel, ClusterState {
|
|||||||
const api = (await this.getProxyKubeconfig()).makeApiClient(CoreV1Api);
|
const api = (await this.getProxyKubeconfig()).makeApiClient(CoreV1Api);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { body: { items } } = await api.listNamespace();
|
const { body: { items }} = await api.listNamespace();
|
||||||
const namespaces = items.map(ns => ns.metadata.name);
|
const namespaces = items.map(ns => ns.metadata.name);
|
||||||
|
|
||||||
return namespaces;
|
return namespaces;
|
||||||
|
|||||||
@ -68,7 +68,7 @@ export class FilesystemProvisionerStore extends BaseStore<FSProvisionModel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
protected fromStore({ extensions }: FSProvisionModel = { extensions: {} }): void {
|
protected fromStore({ extensions }: FSProvisionModel = { extensions: {}}): void {
|
||||||
this.registeredExtensions.merge(extensions);
|
this.registeredExtensions.merge(extensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -346,10 +346,10 @@ export class Kubectl {
|
|||||||
bashScript += `export PATH="${helmPath}:${kubectlPath}:$PATH"\n`;
|
bashScript += `export PATH="${helmPath}:${kubectlPath}:$PATH"\n`;
|
||||||
bashScript += "export KUBECONFIG=\"$tempkubeconfig\"\n";
|
bashScript += "export KUBECONFIG=\"$tempkubeconfig\"\n";
|
||||||
|
|
||||||
bashScript += "NO_PROXY=\",${NO_PROXY:-localhost},\"\n";
|
bashScript += `NO_PROXY=\",\${NO_PROXY:-localhost},\"\n`;
|
||||||
bashScript += "NO_PROXY=\"${NO_PROXY//,localhost,/,}\"\n";
|
bashScript += `NO_PROXY=\"\${NO_PROXY//,localhost,/,}\"\n`;
|
||||||
bashScript += "NO_PROXY=\"${NO_PROXY//,127.0.0.1,/,}\"\n";
|
bashScript += `NO_PROXY=\"\${NO_PROXY//,127.0.0.1,/,}\"\n`;
|
||||||
bashScript += "NO_PROXY=\"localhost,127.0.0.1${NO_PROXY%,}\"\n";
|
bashScript += `NO_PROXY=\"localhost,127.0.0.1\${NO_PROXY%,}\"\n`;
|
||||||
bashScript += "export NO_PROXY\n";
|
bashScript += "export NO_PROXY\n";
|
||||||
bashScript += "unset tempkubeconfig\n";
|
bashScript += "unset tempkubeconfig\n";
|
||||||
await fsPromises.writeFile(bashScriptPath, bashScript.toString(), { mode: 0o644 });
|
await fsPromises.writeFile(bashScriptPath, bashScript.toString(), { mode: 0o644 });
|
||||||
@ -371,14 +371,14 @@ export class Kubectl {
|
|||||||
zshScript += `helmpath=\"${helmPath}"\n`;
|
zshScript += `helmpath=\"${helmPath}"\n`;
|
||||||
zshScript += "p=\":$kubectlpath:\"\n";
|
zshScript += "p=\":$kubectlpath:\"\n";
|
||||||
zshScript += "d=\":$PATH:\"\n";
|
zshScript += "d=\":$PATH:\"\n";
|
||||||
zshScript += "d=${d//$p/:}\n";
|
zshScript += `d=\${d//$p/:}\n`;
|
||||||
zshScript += "d=${d/#:/}\n";
|
zshScript += `d=\${d/#:/}\n`;
|
||||||
zshScript += "export PATH=\"$helmpath:$kubectlpath:${d/%:/}\"\n";
|
zshScript += `export PATH=\"$helmpath:$kubectlpath:\${d/%:/}\"\n`;
|
||||||
zshScript += "export KUBECONFIG=\"$tempkubeconfig\"\n";
|
zshScript += "export KUBECONFIG=\"$tempkubeconfig\"\n";
|
||||||
zshScript += "NO_PROXY=\",${NO_PROXY:-localhost},\"\n";
|
zshScript += `NO_PROXY=\",\${NO_PROXY:-localhost},\"\n`;
|
||||||
zshScript += "NO_PROXY=\"${NO_PROXY//,localhost,/,}\"\n";
|
zshScript += `NO_PROXY=\"\${NO_PROXY//,localhost,/,}\"\n`;
|
||||||
zshScript += "NO_PROXY=\"${NO_PROXY//,127.0.0.1,/,}\"\n";
|
zshScript += `NO_PROXY=\"\${NO_PROXY//,127.0.0.1,/,}\"\n`;
|
||||||
zshScript += "NO_PROXY=\"localhost,127.0.0.1${NO_PROXY%,}\"\n";
|
zshScript += `NO_PROXY=\"localhost,127.0.0.1\${NO_PROXY%,}\"\n`;
|
||||||
zshScript += "export NO_PROXY\n";
|
zshScript += "export NO_PROXY\n";
|
||||||
zshScript += "unset tempkubeconfig\n";
|
zshScript += "unset tempkubeconfig\n";
|
||||||
zshScript += "unset OLD_ZDOTDIR\n";
|
zshScript += "unset OLD_ZDOTDIR\n";
|
||||||
|
|||||||
@ -46,7 +46,7 @@ export abstract class PrometheusProvider {
|
|||||||
protected async getFirstNamespacedServer(client: CoreV1Api, ...selectors: string[]): Promise<PrometheusService | undefined> {
|
protected async getFirstNamespacedServer(client: CoreV1Api, ...selectors: string[]): Promise<PrometheusService | undefined> {
|
||||||
try {
|
try {
|
||||||
for (const selector of selectors) {
|
for (const selector of selectors) {
|
||||||
const { body: { items: [service] } } = await client.listServiceForAllNamespaces(null, null, null, selector);
|
const { body: { items: [service] }} = await client.listServiceForAllNamespaces(null, null, null, selector);
|
||||||
|
|
||||||
if (service) {
|
if (service) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -122,7 +122,7 @@ export class Router {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static async handleStaticFile({ params, response, raw: { req } }: LensApiRequest): Promise<void> {
|
protected static async handleStaticFile({ params, response, raw: { req }}: LensApiRequest): Promise<void> {
|
||||||
let filePath = params.path;
|
let filePath = params.path;
|
||||||
|
|
||||||
for (let retryCount = 0; retryCount < 5; retryCount += 1) {
|
for (let retryCount = 0; retryCount < 5; retryCount += 1) {
|
||||||
|
|||||||
@ -63,7 +63,7 @@ function generateKubeConfig(username: string, secret: V1Secret, cluster: Cluster
|
|||||||
|
|
||||||
export class KubeconfigRoute {
|
export class KubeconfigRoute {
|
||||||
static async routeServiceAccountRoute(request: LensApiRequest) {
|
static async routeServiceAccountRoute(request: LensApiRequest) {
|
||||||
const { params, response, cluster} = request;
|
const { params, response, cluster } = request;
|
||||||
const client = (await cluster.getProxyKubeconfig()).makeApiClient(CoreV1Api);
|
const client = (await cluster.getProxyKubeconfig()).makeApiClient(CoreV1Api);
|
||||||
const secretList = await client.listNamespacedSecret(params.namespace);
|
const secretList = await client.listNamespacedSecret(params.namespace);
|
||||||
const secret = secretList.body.items.find(secret => {
|
const secret = secretList.body.items.find(secret => {
|
||||||
|
|||||||
@ -27,6 +27,6 @@ export class VersionRoute {
|
|||||||
static async getVersion(request: LensApiRequest) {
|
static async getVersion(request: LensApiRequest) {
|
||||||
const { response } = request;
|
const { response } = request;
|
||||||
|
|
||||||
respondJson(response, { version: getAppVersion()}, 200);
|
respondJson(response, { version: getAppVersion() }, 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@ export default {
|
|||||||
if (contextName === "__internal__") continue;
|
if (contextName === "__internal__") continue;
|
||||||
const cluster = value[1];
|
const cluster = value[1];
|
||||||
|
|
||||||
store.set(contextName, { kubeConfig: cluster.kubeConfig, icon: cluster.icon || null, preferences: cluster.preferences || {} });
|
store.set(contextName, { kubeConfig: cluster.kubeConfig, icon: cluster.icon || null, preferences: cluster.preferences || {}});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} as MigrationDeclaration;
|
} as MigrationDeclaration;
|
||||||
|
|||||||
@ -28,9 +28,9 @@ export default {
|
|||||||
version: "5.0.0-alpha.0",
|
version: "5.0.0-alpha.0",
|
||||||
run(store) {
|
run(store) {
|
||||||
const hotbar = getEmptyHotbar("default");
|
const hotbar = getEmptyHotbar("default");
|
||||||
const { metadata: { uid, name, source } } = catalogEntity;
|
const { metadata: { uid, name, source }} = catalogEntity;
|
||||||
|
|
||||||
hotbar.items[0] = { entity: { uid, name, source } };
|
hotbar.items[0] = { entity: { uid, name, source }};
|
||||||
|
|
||||||
store.set("hotbars", [hotbar]);
|
store.set("hotbars", [hotbar]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,9 +53,9 @@ export default {
|
|||||||
// Hotbars might be empty, if some of the previous migrations weren't run
|
// Hotbars might be empty, if some of the previous migrations weren't run
|
||||||
if (hotbars.length === 0) {
|
if (hotbars.length === 0) {
|
||||||
const hotbar = getEmptyHotbar("default");
|
const hotbar = getEmptyHotbar("default");
|
||||||
const { metadata: { uid, name, source } } = catalogEntity;
|
const { metadata: { uid, name, source }} = catalogEntity;
|
||||||
|
|
||||||
hotbar.items[0] = { entity: { uid, name, source } };
|
hotbar.items[0] = { entity: { uid, name, source }};
|
||||||
|
|
||||||
hotbars.push(hotbar);
|
hotbars.push(hotbar);
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ export default {
|
|||||||
if (hotbars.every(hotbar => hotbar.items.every(item => item?.entity?.uid !== "catalog-entity"))) {
|
if (hotbars.every(hotbar => hotbar.items.every(item => item?.entity?.uid !== "catalog-entity"))) {
|
||||||
// note, we will add a new whole hotbar here called "default" if that was previously removed
|
// note, we will add a new whole hotbar here called "default" if that was previously removed
|
||||||
const defaultHotbar = hotbars.find(hotbar => hotbar.name === "default");
|
const defaultHotbar = hotbars.find(hotbar => hotbar.name === "default");
|
||||||
const { metadata: { uid, name, source } } = catalogEntity;
|
const { metadata: { uid, name, source }} = catalogEntity;
|
||||||
|
|
||||||
if (defaultHotbar) {
|
if (defaultHotbar) {
|
||||||
const freeIndex = defaultHotbar.items.findIndex(isNull);
|
const freeIndex = defaultHotbar.items.findIndex(isNull);
|
||||||
@ -142,15 +142,15 @@ export default {
|
|||||||
// called "default" is full than overriding a hotbar item
|
// called "default" is full than overriding a hotbar item
|
||||||
const hotbar = getEmptyHotbar("initial");
|
const hotbar = getEmptyHotbar("initial");
|
||||||
|
|
||||||
hotbar.items[0] = { entity: { uid, name, source } };
|
hotbar.items[0] = { entity: { uid, name, source }};
|
||||||
hotbars.unshift(hotbar);
|
hotbars.unshift(hotbar);
|
||||||
} else {
|
} else {
|
||||||
defaultHotbar.items[freeIndex] = { entity: { uid, name, source } };
|
defaultHotbar.items[freeIndex] = { entity: { uid, name, source }};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const hotbar = getEmptyHotbar("default");
|
const hotbar = getEmptyHotbar("default");
|
||||||
|
|
||||||
hotbar.items[0] = { entity: { uid, name, source } };
|
hotbar.items[0] = { entity: { uid, name, source }};
|
||||||
hotbars.unshift(hotbar);
|
hotbars.unshift(hotbar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,7 +91,7 @@ export class HelmChartDetails extends Component<Props> {
|
|||||||
try {
|
try {
|
||||||
this.abortController?.abort();
|
this.abortController?.abort();
|
||||||
this.abortController = new AbortController();
|
this.abortController = new AbortController();
|
||||||
const { chart: { name, repo } } = this.props;
|
const { chart: { name, repo }} = this.props;
|
||||||
const { readme } = await getChartDetails(repo, name, { version: chart.version, reqInit: { signal: this.abortController.signal }});
|
const { readme } = await getChartDetails(repo, name, { version: chart.version, reqInit: { signal: this.abortController.signal }});
|
||||||
|
|
||||||
this.readme = readme;
|
this.readme = readme;
|
||||||
|
|||||||
@ -50,7 +50,7 @@ export class HelmCharts extends Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get selectedChart() {
|
get selectedChart() {
|
||||||
const { match: { params: { chartName, repo } } } = this.props;
|
const { match: { params: { chartName, repo }}} = this.props;
|
||||||
|
|
||||||
return helmChartStore.getByName(chartName, repo);
|
return helmChartStore.getByName(chartName, repo);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,7 +55,7 @@ interface Props extends RouteComponentProps<ReleaseRouteParams> {
|
|||||||
@observer
|
@observer
|
||||||
export class HelmReleases extends Component<Props> {
|
export class HelmReleases extends Component<Props> {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const { match: { params: { namespace } } } = this.props;
|
const { match: { params: { namespace }}} = this.props;
|
||||||
|
|
||||||
if (namespace) {
|
if (namespace) {
|
||||||
namespaceStore.selectNamespaces(namespace);
|
namespaceStore.selectNamespaces(namespace);
|
||||||
@ -68,7 +68,7 @@ export class HelmReleases extends Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get selectedRelease() {
|
get selectedRelease() {
|
||||||
const { match: { params: { name, namespace } } } = this.props;
|
const { match: { params: { name, namespace }}} = this.props;
|
||||||
|
|
||||||
return releaseStore.items.find(release => {
|
return releaseStore.items.find(release => {
|
||||||
return release.getName() == name && release.getNs() == namespace;
|
return release.getName() == name && release.getNs() == namespace;
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export class CatalogEntityStore extends ItemStore<CatalogEntityItem<CatalogEntit
|
|||||||
watch() {
|
watch() {
|
||||||
return disposer(
|
return disposer(
|
||||||
reaction(() => this.entities, () => this.loadAll()),
|
reaction(() => this.entities, () => this.loadAll()),
|
||||||
reaction(() => this.activeCategory, () => this.loadAll(), { delay: 100}),
|
reaction(() => this.activeCategory, () => this.loadAll(), { delay: 100 }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -109,7 +109,7 @@ export class Catalog extends React.Component<Props> {
|
|||||||
console.error(error);
|
console.error(error);
|
||||||
Notifications.error(<p>Unknown category: {routeTab}</p>);
|
Notifications.error(<p>Unknown category: {routeTab}</p>);
|
||||||
}
|
}
|
||||||
}, {fireImmediately: true}),
|
}, { fireImmediately: true }),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// If active category is filtered out, automatically switch to the first category
|
// If active category is filtered out, automatically switch to the first category
|
||||||
@ -169,7 +169,7 @@ export class Catalog extends React.Component<Props> {
|
|||||||
const activeCategory = this.categories.find(category => category.getId() === tabId);
|
const activeCategory = this.categories.find(category => category.getId() === tabId);
|
||||||
|
|
||||||
if (activeCategory) {
|
if (activeCategory) {
|
||||||
navigate(catalogURL({ params: {group: activeCategory.spec.group, kind: activeCategory.spec.names.kind }}));
|
navigate(catalogURL({ params: { group: activeCategory.spec.group, kind: activeCategory.spec.names.kind }}));
|
||||||
} else {
|
} else {
|
||||||
navigate(catalogURL({ params: { group: browseCatalogTab }}));
|
navigate(catalogURL({ params: { group: browseCatalogTab }}));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,14 +27,17 @@ import type { CatalogEntity } from "../../api/catalog-entity";
|
|||||||
|
|
||||||
export function HotbarToggleMenuItem(props: { entity: CatalogEntity, addContent: ReactNode, removeContent: ReactNode }) {
|
export function HotbarToggleMenuItem(props: { entity: CatalogEntity, addContent: ReactNode, removeContent: ReactNode }) {
|
||||||
const store = HotbarStore.getInstance();
|
const store = HotbarStore.getInstance();
|
||||||
const add = () => store.addToHotbar(props.entity);
|
|
||||||
const remove = () => store.removeFromHotbar(props.entity.getId());
|
|
||||||
const [itemInHotbar, setItemInHotbar] = useState(store.isAddedToActive(props.entity));
|
const [itemInHotbar, setItemInHotbar] = useState(store.isAddedToActive(props.entity));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem onClick={() => {
|
<MenuItem onClick={() => {
|
||||||
itemInHotbar ? remove() : add();
|
if (itemInHotbar) {
|
||||||
setItemInHotbar(!itemInHotbar);
|
store.removeFromHotbar(props.entity.getId());
|
||||||
|
setItemInHotbar(false);
|
||||||
|
} else {
|
||||||
|
store.addToHotbar(props.entity);
|
||||||
|
setItemInHotbar(true);
|
||||||
|
}
|
||||||
}}>
|
}}>
|
||||||
{itemInHotbar ? props.removeContent : props.addContent }
|
{itemInHotbar ? props.removeContent : props.addContent }
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
|||||||
@ -48,7 +48,7 @@ function transformUnit(name: string, value: string): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderQuotas(quota: ResourceQuota): JSX.Element[] {
|
function renderQuotas(quota: ResourceQuota): JSX.Element[] {
|
||||||
const { hard = {}, used = {} } = quota.status;
|
const { hard = {}, used = {}} = quota.status;
|
||||||
|
|
||||||
return Object.entries(hard)
|
return Object.entries(hard)
|
||||||
.filter(([name]) => used[name])
|
.filter(([name]) => used[name])
|
||||||
|
|||||||
@ -153,7 +153,7 @@ export class CRDDetails extends React.Component<Props> {
|
|||||||
{validation &&
|
{validation &&
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Validation"/>
|
<DrawerTitle title="Validation"/>
|
||||||
<MonacoEditor readOnly value={validation}/>
|
<MonacoEditor readOnly value={validation}/>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -96,7 +96,7 @@ export class CrdResourceDetails extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { props: { object, crd } } = this;
|
const { props: { object, crd }} = this;
|
||||||
|
|
||||||
if (!object || !crd) {
|
if (!object || !crd) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -246,7 +246,7 @@ async function createTempFilesAndValidate({ fileName, dataP }: InstallRequest):
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function unpackExtension(request: InstallRequestValidated, disposeDownloading?: Disposer) {
|
async function unpackExtension(request: InstallRequestValidated, disposeDownloading?: Disposer) {
|
||||||
const { id, fileName, tempFile, manifest: { name, version } } = request;
|
const { id, fileName, tempFile, manifest: { name, version }} = request;
|
||||||
|
|
||||||
ExtensionInstallationStateStore.setInstalling(id);
|
ExtensionInstallationStateStore.setInstalling(id);
|
||||||
disposeDownloading?.();
|
disposeDownloading?.();
|
||||||
@ -386,7 +386,7 @@ async function attemptInstall(request: InstallRequest, d?: ExtendableDisposer):
|
|||||||
// install extension if not yet exists
|
// install extension if not yet exists
|
||||||
await unpackExtension(validatedRequest, dispose);
|
await unpackExtension(validatedRequest, dispose);
|
||||||
} else {
|
} else {
|
||||||
const { manifest: { version: oldVersion } } = ExtensionLoader.getInstance().getExtension(validatedRequest.id);
|
const { manifest: { version: oldVersion }} = ExtensionLoader.getInstance().getExtension(validatedRequest.id);
|
||||||
|
|
||||||
// otherwise confirmation required (re-install / update)
|
// otherwise confirmation required (re-install / update)
|
||||||
const removeNotification = Notifications.info(
|
const removeNotification = Notifications.info(
|
||||||
@ -451,7 +451,7 @@ async function installFromInput(input: string) {
|
|||||||
|
|
||||||
await attemptInstall({ fileName, dataP: readFileNotify(input) });
|
await attemptInstall({ fileName, dataP: readFileNotify(input) });
|
||||||
} else if (InputValidators.isExtensionNameInstall.validate(input)) {
|
} else if (InputValidators.isExtensionNameInstall.validate(input)) {
|
||||||
const [{ groups: { name, version } }] = [...input.matchAll(InputValidators.isExtensionNameInstallRegex)];
|
const [{ groups: { name, version }}] = [...input.matchAll(InputValidators.isExtensionNameInstallRegex)];
|
||||||
|
|
||||||
await attemptInstallByInfo({ name, version });
|
await attemptInstallByInfo({ name, version });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,7 +106,7 @@ export const InstalledExtensions = observer(({ extensions, uninstall, enable, di
|
|||||||
),
|
),
|
||||||
version,
|
version,
|
||||||
status: (
|
status: (
|
||||||
<div className={cssNames({[styles.enabled]: isEnabled, [styles.invalid]: !isCompatible})}>
|
<div className={cssNames({ [styles.enabled]: isEnabled, [styles.invalid]: !isCompatible })}>
|
||||||
{getStatus(extension)}
|
{getStatus(extension)}
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import "./endpoint-subset-list.scss";
|
|||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { EndpointSubset, Endpoint, EndpointAddress} from "../../../common/k8s-api/endpoints";
|
import { EndpointSubset, Endpoint, EndpointAddress } from "../../../common/k8s-api/endpoints";
|
||||||
import { Table, TableCell, TableHead, TableRow } from "../table";
|
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||||
import { boundMethod } from "../../utils";
|
import { boundMethod } from "../../utils";
|
||||||
import { apiManager } from "../../../common/k8s-api/api-manager";
|
import { apiManager } from "../../../common/k8s-api/api-manager";
|
||||||
@ -47,7 +47,7 @@ export class EndpointSubsetList extends React.Component<Props> {
|
|||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
getNotReadyAddressTableRow(ip: string) {
|
getNotReadyAddressTableRow(ip: string) {
|
||||||
const { subset} = this.props;
|
const { subset } = this.props;
|
||||||
const address = subset.getNotReadyAddresses().find(address => address.getId() == ip);
|
const address = subset.getNotReadyAddresses().find(address => address.getId() == ip);
|
||||||
|
|
||||||
return this.renderAddressTableRow(address);
|
return this.renderAddressTableRow(address);
|
||||||
|
|||||||
@ -62,7 +62,7 @@ export class IngressDetails extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderPaths(ingress: Ingress) {
|
renderPaths(ingress: Ingress) {
|
||||||
const { spec: { rules } } = ingress;
|
const { spec: { rules }} = ingress;
|
||||||
|
|
||||||
if (!rules || !rules.length) return null;
|
if (!rules || !rules.length) return null;
|
||||||
|
|
||||||
|
|||||||
@ -95,7 +95,7 @@ export class NetworkPolicyDetails extends React.Component<Props> {
|
|||||||
<>
|
<>
|
||||||
<SubTitle title="To"/>
|
<SubTitle title="To"/>
|
||||||
{to.map(item => {
|
{to.map(item => {
|
||||||
const { ipBlock: { cidr, except } = {} } = item;
|
const { ipBlock: { cidr, except } = {}} = item;
|
||||||
|
|
||||||
if (!cidr) return null;
|
if (!cidr) return null;
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export class PortForwards extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get selectedPortForward() {
|
get selectedPortForward() {
|
||||||
const { match: { params: { forwardport } } } = this.props;
|
const { match: { params: { forwardport }}} = this.props;
|
||||||
|
|
||||||
return portForwardStore.getById(forwardport);
|
return portForwardStore.getById(forwardport);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -67,6 +67,11 @@ export class ServiceDetails extends React.Component<Props> {
|
|||||||
|
|
||||||
const { spec } = service;
|
const { spec } = service;
|
||||||
const endpoint = endpointStore.getByName(service.getName(), service.getNs());
|
const endpoint = endpointStore.getByName(service.getName(), service.getNs());
|
||||||
|
const externalIps = service.getExternalIps();
|
||||||
|
|
||||||
|
if (externalIps.length === 0 && spec?.externalName) {
|
||||||
|
externalIps.push(spec.externalName);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ServicesDetails">
|
<div className="ServicesDetails">
|
||||||
@ -106,9 +111,9 @@ export class ServiceDetails extends React.Component<Props> {
|
|||||||
{service.getIpFamilyPolicy()}
|
{service.getIpFamilyPolicy()}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|
||||||
{service.getExternalIps().length > 0 && (
|
{externalIps.length > 0 && (
|
||||||
<DrawerItem name="External IPs">
|
<DrawerItem name="External IPs">
|
||||||
{service.getExternalIps().map(ip => <div key={ip}>{ip}</div>)}
|
{externalIps.map(ip => <div key={ip}>{ip}</div>)}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -81,18 +81,26 @@ export class Services extends React.Component<Props> {
|
|||||||
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
{ title: "Age", className: "age", sortBy: columnId.age, id: columnId.age },
|
||||||
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
|
{ title: "Status", className: "status", sortBy: columnId.status, id: columnId.status },
|
||||||
]}
|
]}
|
||||||
renderTableContents={service => [
|
renderTableContents={service => {
|
||||||
service.getName(),
|
const externalIps = service.getExternalIps();
|
||||||
<KubeObjectStatusIcon key="icon" object={service} />,
|
|
||||||
service.getNs(),
|
if (externalIps.length === 0 && service.spec?.externalName) {
|
||||||
service.getType(),
|
externalIps.push(service.spec.externalName);
|
||||||
service.getClusterIp(),
|
}
|
||||||
service.getPorts().join(", "),
|
|
||||||
service.getExternalIps().join(", ") || "-",
|
return [
|
||||||
service.getSelector().map(label => <Badge key={label} label={label}/>),
|
service.getName(),
|
||||||
service.getAge(),
|
<KubeObjectStatusIcon key="icon" object={service} />,
|
||||||
{ title: service.getStatus(), className: service.getStatus().toLowerCase() },
|
service.getNs(),
|
||||||
]}
|
service.getType(),
|
||||||
|
service.getClusterIp(),
|
||||||
|
service.getPorts().join(", "),
|
||||||
|
externalIps.join(", ") || "-",
|
||||||
|
service.getSelector().map(label => <Badge key={label} label={label} />),
|
||||||
|
service.getAge(),
|
||||||
|
{ title: service.getStatus(), className: service.getStatus().toLowerCase() },
|
||||||
|
];
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,7 @@ const dialogState = observable.object({
|
|||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class AddHelmRepoDialog extends React.Component<Props> {
|
export class AddHelmRepoDialog extends React.Component<Props> {
|
||||||
private emptyRepo = {name: "", url: "", username: "", password: "", insecureSkipTlsVerify: false, caFile:"", keyFile: "", certFile: ""};
|
private emptyRepo = { name: "", url: "", username: "", password: "", insecureSkipTlsVerify: false, caFile:"", keyFile: "", certFile: "" };
|
||||||
|
|
||||||
private static keyExtensions = ["key", "keystore", "jks", "p12", "pfx", "pem"];
|
private static keyExtensions = ["key", "keystore", "jks", "p12", "pfx", "pem"];
|
||||||
private static certExtensions = ["crt", "cer", "ca-bundle", "p7b", "p7c" , "p7s", "p12", "pfx", "pem"];
|
private static certExtensions = ["crt", "cer", "ca-bundle", "p7b", "p7c" , "p7s", "p12", "pfx", "pem"];
|
||||||
@ -96,7 +96,7 @@ export class AddHelmRepoDialog extends React.Component<Props> {
|
|||||||
buttonLabel: `Use file`,
|
buttonLabel: `Use file`,
|
||||||
filters: [
|
filters: [
|
||||||
fileFilter,
|
fileFilter,
|
||||||
{ name: "Any", extensions: ["*"]}
|
{ name: "Any", extensions: ["*"] }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ export class AddHelmRepoDialog extends React.Component<Props> {
|
|||||||
/>
|
/>
|
||||||
<Icon
|
<Icon
|
||||||
material="folder"
|
material="folder"
|
||||||
onClick={() => this.selectFileDialog(fileType, {name: placeholder, extensions: fileExtensions})}
|
onClick={() => this.selectFileDialog(fileType, { name: placeholder, extensions: fileExtensions })}
|
||||||
tooltip="Browse"
|
tooltip="Browse"
|
||||||
/>
|
/>
|
||||||
</div>);
|
</div>);
|
||||||
|
|||||||
@ -46,7 +46,7 @@ interface Value {
|
|||||||
info: SyncInfo;
|
info: SyncInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getMapEntry({ filePath, ...data}: KubeconfigSyncEntry): Promise<[string, Value]> {
|
async function getMapEntry({ filePath, ...data }: KubeconfigSyncEntry): Promise<[string, Value]> {
|
||||||
try {
|
try {
|
||||||
// stat follows the stat(2) linux syscall spec, namely it follows symlinks
|
// stat follows the stat(2) linux syscall spec, namely it follows symlinks
|
||||||
const stats = await fse.stat(filePath);
|
const stats = await fse.stat(filePath);
|
||||||
|
|||||||
@ -106,7 +106,7 @@ export class Preferences extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ExtensionSettings({ title, id, components: { Hint, Input } }: RegisteredAppPreference) {
|
export function ExtensionSettings({ title, id, components: { Hint, Input }}: RegisteredAppPreference) {
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<section id={id} className="small">
|
<section id={id} className="small">
|
||||||
|
|||||||
@ -31,7 +31,7 @@ interface Props extends DOMAttributes<any>{
|
|||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function RemovableItem({icon, onRemove, children, className, ...rest}: Props) {
|
export function RemovableItem({ icon, onRemove, children, className, ...rest }: Props) {
|
||||||
return (
|
return (
|
||||||
<div className={cssNames(styles.item, "flex gaps align-center justify-space-between", className)} {...rest}>
|
<div className={cssNames(styles.item, "flex gaps align-center justify-space-between", className)} {...rest}>
|
||||||
{icon && (
|
{icon && (
|
||||||
|
|||||||
@ -59,7 +59,7 @@ export class ServiceAccountsDetails extends React.Component<Props> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.secrets = await Promise.all(secrets);
|
this.secrets = await Promise.all(secrets);
|
||||||
const imagePullSecrets = serviceAccount.getImagePullSecrets().map(async({ name }) => {
|
const imagePullSecrets = serviceAccount.getImagePullSecrets().map(async ({ name }) => {
|
||||||
return secretsStore.load({ name, namespace }).catch(() => this.generateDummySecretObject(name));
|
return secretsStore.load({ name, namespace }).catch(() => this.generateDummySecretObject(name));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ const dummyDeployment: Deployment = {
|
|||||||
selfLink: "link",
|
selfLink: "link",
|
||||||
spec: {
|
spec: {
|
||||||
replicas: 1,
|
replicas: 1,
|
||||||
selector: { matchLabels: { dummy: "label" } },
|
selector: { matchLabels: { dummy: "label" }},
|
||||||
template: {
|
template: {
|
||||||
metadata: {
|
metadata: {
|
||||||
labels: { dummy: "label" },
|
labels: { dummy: "label" },
|
||||||
|
|||||||
@ -118,12 +118,14 @@ export class DeploymentScaleDialog extends Component<Props> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private readonly scaleMin = 0;
|
||||||
|
|
||||||
desiredReplicasUp = () => {
|
desiredReplicasUp = () => {
|
||||||
this.desiredReplicas < this.scaleMax && this.desiredReplicas++;
|
this.desiredReplicas = Math.min(this.scaleMax, this.desiredReplicas + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
desiredReplicasDown = () => {
|
desiredReplicasDown = () => {
|
||||||
this.desiredReplicas > 0 && this.desiredReplicas--;
|
this.desiredReplicas = Math.max(this.scaleMin, this.desiredReplicas - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderContents() {
|
renderContents() {
|
||||||
|
|||||||
@ -40,30 +40,23 @@ interface Props {
|
|||||||
export const ContainerEnvironment = observer((props: Props) => {
|
export const ContainerEnvironment = observer((props: Props) => {
|
||||||
const { container: { env, envFrom }, namespace } = props;
|
const { container: { env, envFrom }, namespace } = props;
|
||||||
|
|
||||||
useEffect(
|
useEffect( () => autorun(() => {
|
||||||
() =>
|
for (const { valueFrom } of env ?? []) {
|
||||||
autorun(() => {
|
if (valueFrom?.configMapKeyRef) {
|
||||||
env && env.forEach(variable => {
|
configMapsStore.load({ name: valueFrom.configMapKeyRef.name, namespace });
|
||||||
const { valueFrom } = variable;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (valueFrom && valueFrom.configMapKeyRef) {
|
for (const { configMapRef, secretRef } of envFrom ?? []) {
|
||||||
configMapsStore.load({ name: valueFrom.configMapKeyRef.name, namespace });
|
if (secretRef?.name) {
|
||||||
}
|
secretsStore.load({ name: secretRef.name, namespace });
|
||||||
});
|
}
|
||||||
envFrom && envFrom.forEach(item => {
|
|
||||||
const { configMapRef, secretRef } = item;
|
|
||||||
|
|
||||||
if (secretRef && secretRef.name) {
|
if (configMapRef?.name) {
|
||||||
secretsStore.load({ name: secretRef.name, namespace });
|
configMapsStore.load({ name: configMapRef.name, namespace });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (configMapRef && configMapRef.name) {
|
}), []);
|
||||||
configMapsStore.load({ name: configMapRef.name, namespace });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderEnv = () => {
|
const renderEnv = () => {
|
||||||
const orderedEnv = _.sortBy(env, "name");
|
const orderedEnv = _.sortBy(env, "name");
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export class PodDetailsAffinities extends React.Component<Props> {
|
|||||||
<DrawerItem name="Affinities" className="PodDetailsAffinities">
|
<DrawerItem name="Affinities" className="PodDetailsAffinities">
|
||||||
<DrawerParamToggler label={affinitiesNum}>
|
<DrawerParamToggler label={affinitiesNum}>
|
||||||
<div style={{ height: 200 }}>
|
<div style={{ height: 200 }}>
|
||||||
<MonacoEditor readOnly value={yaml.dump(affinities)}/>
|
<MonacoEditor readOnly value={yaml.dump(affinities)}/>
|
||||||
</div>
|
</div>
|
||||||
</DrawerParamToggler>
|
</DrawerParamToggler>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|||||||
@ -118,12 +118,14 @@ export class ReplicaSetScaleDialog extends Component<Props> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private readonly scaleMin = 0;
|
||||||
|
|
||||||
desiredReplicasUp = () => {
|
desiredReplicasUp = () => {
|
||||||
this.desiredReplicas < this.scaleMax && this.desiredReplicas++;
|
this.desiredReplicas = Math.min(this.scaleMax, this.desiredReplicas + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
desiredReplicasDown = () => {
|
desiredReplicasDown = () => {
|
||||||
this.desiredReplicas > 0 && this.desiredReplicas--;
|
this.desiredReplicas = Math.max(this.scaleMin, this.desiredReplicas - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderContents() {
|
renderContents() {
|
||||||
|
|||||||
@ -117,12 +117,14 @@ export class StatefulSetScaleDialog extends Component<Props> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private readonly scaleMin = 0;
|
||||||
|
|
||||||
desiredReplicasUp = () => {
|
desiredReplicasUp = () => {
|
||||||
this.desiredReplicas < this.scaleMax && this.desiredReplicas++;
|
this.desiredReplicas = Math.min(this.scaleMax, this.desiredReplicas + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
desiredReplicasDown = () => {
|
desiredReplicasDown = () => {
|
||||||
this.desiredReplicas > 0 && this.desiredReplicas--;
|
this.desiredReplicas = Math.max(this.scaleMin, this.desiredReplicas - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
renderContents() {
|
renderContents() {
|
||||||
|
|||||||
@ -60,7 +60,7 @@ const runningDeployment = new Deployment({
|
|||||||
|
|
||||||
runningDeployment.spec = {
|
runningDeployment.spec = {
|
||||||
replicas: 1,
|
replicas: 1,
|
||||||
selector: { matchLabels: {} },
|
selector: { matchLabels: {}},
|
||||||
strategy: {
|
strategy: {
|
||||||
type: "test",
|
type: "test",
|
||||||
rollingUpdate: {
|
rollingUpdate: {
|
||||||
@ -91,7 +91,7 @@ const failedDeployment = new Deployment({
|
|||||||
|
|
||||||
failedDeployment.spec = {
|
failedDeployment.spec = {
|
||||||
replicas: 1,
|
replicas: 1,
|
||||||
selector: { matchLabels: {} },
|
selector: { matchLabels: {}},
|
||||||
strategy: {
|
strategy: {
|
||||||
type: "test",
|
type: "test",
|
||||||
rollingUpdate: {
|
rollingUpdate: {
|
||||||
@ -122,7 +122,7 @@ const pendingDeployment = new Deployment({
|
|||||||
|
|
||||||
pendingDeployment.spec = {
|
pendingDeployment.spec = {
|
||||||
replicas: 1,
|
replicas: 1,
|
||||||
selector: { matchLabels: {} },
|
selector: { matchLabels: {}},
|
||||||
strategy: {
|
strategy: {
|
||||||
type: "test",
|
type: "test",
|
||||||
rollingUpdate: {
|
rollingUpdate: {
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export class ClusterManager extends React.Component {
|
|||||||
<Route component={EntitySettings} {...routes.entitySettingsRoute} />
|
<Route component={EntitySettings} {...routes.entitySettingsRoute} />
|
||||||
{
|
{
|
||||||
GlobalPageRegistry.getInstance().getItems()
|
GlobalPageRegistry.getInstance().getItems()
|
||||||
.map(({ url, components: { Page } }) => (
|
.map(({ url, components: { Page }}) => (
|
||||||
<Route key={url} path={url} component={Page} />
|
<Route key={url} path={url} component={Page} />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -119,7 +119,7 @@ export function MetricsSettings({ entity }: EntitySettingViewProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function NodeShellSettings({entity}: EntitySettingViewProps) {
|
export function NodeShellSettings({ entity }: EntitySettingViewProps) {
|
||||||
const cluster = getClusterForEntity(entity);
|
const cluster = getClusterForEntity(entity);
|
||||||
|
|
||||||
if(!cluster) {
|
if(!cluster) {
|
||||||
|
|||||||
@ -109,7 +109,7 @@ export class Drawer extends React.Component<DrawerProps> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
onClickOutside = (evt: MouseEvent) => {
|
onClickOutside = (evt: MouseEvent) => {
|
||||||
const { contentElem, mouseDownTarget, close, props: { open } } = this;
|
const { contentElem, mouseDownTarget, close, props: { open }} = this;
|
||||||
|
|
||||||
if (!open || evt.defaultPrevented || contentElem.contains(mouseDownTarget)) {
|
if (!open || evt.defaultPrevented || contentElem.contains(mouseDownTarget)) {
|
||||||
return;
|
return;
|
||||||
@ -139,9 +139,9 @@ export class Drawer extends React.Component<DrawerProps> {
|
|||||||
const k8sObjName = title.split(":")[1] || title; // copy whole if no :
|
const k8sObjName = title.split(":")[1] || title; // copy whole if no :
|
||||||
|
|
||||||
clipboard.writeText(k8sObjName.trim());
|
clipboard.writeText(k8sObjName.trim());
|
||||||
this.setState({isCopied: true});
|
this.setState({ isCopied: true });
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.setState({isCopied: false});
|
this.setState({ isCopied: false });
|
||||||
}, 3000);
|
}, 3000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -47,7 +47,7 @@ jest.mock("electron", () => ({
|
|||||||
|
|
||||||
AppPaths.init();
|
AppPaths.init();
|
||||||
|
|
||||||
const mockHotbars: {[id: string]: any} = {
|
const mockHotbars: { [id: string]: any } = {
|
||||||
"1": {
|
"1": {
|
||||||
id: "1",
|
id: "1",
|
||||||
name: "Default",
|
name: "Default",
|
||||||
|
|||||||
@ -74,7 +74,7 @@ export class HotbarEntityIcon extends React.Component<Props> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const className = cssNames("led", { online: this.props.entity.status.phase === LensKubernetesClusterStatus.CONNECTED}); // TODO: make it more generic
|
const className = cssNames("led", { online: this.props.entity.status.phase === LensKubernetesClusterStatus.CONNECTED }); // TODO: make it more generic
|
||||||
|
|
||||||
return <div className={className} />;
|
return <div className={className} />;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -65,7 +65,7 @@ function onMenuItemClick(menuItem: CatalogEntityContextMenu) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const HotbarIcon = observer(({menuItems = [], size = 40, tooltip, ...props}: HotbarIconProps) => {
|
export const HotbarIcon = observer(({ menuItems = [], size = 40, tooltip, ...props }: HotbarIconProps) => {
|
||||||
const { uid, title, src, material, active, className, source, disabled, onMenuOpen, onClick, children, ...rest } = props;
|
const { uid, title, src, material, active, className, source, disabled, onMenuOpen, onClick, children, ...rest } = props;
|
||||||
const id = `hotbarIcon-${uid}`;
|
const id = `hotbarIcon-${uid}`;
|
||||||
const [menuOpen, setMenuOpen] = useState(false);
|
const [menuOpen, setMenuOpen] = useState(false);
|
||||||
@ -104,7 +104,7 @@ export const HotbarIcon = observer(({menuItems = [], size = 40, tooltip, ...prop
|
|||||||
className="HotbarIconMenu"
|
className="HotbarIconMenu"
|
||||||
isOpen={menuOpen}
|
isOpen={menuOpen}
|
||||||
toggleEvent="contextmenu"
|
toggleEvent="contextmenu"
|
||||||
position={{right: true, bottom: true }} // FIXME: position does not work
|
position={{ right: true, bottom: true }} // FIXME: position does not work
|
||||||
open={() => {
|
open={() => {
|
||||||
onMenuOpen?.();
|
onMenuOpen?.();
|
||||||
toggleMenu();
|
toggleMenu();
|
||||||
|
|||||||
@ -89,7 +89,7 @@ export class KubeObjectMenu<T extends KubeObject> extends React.Component<KubeOb
|
|||||||
return KubeObjectMenuRegistry
|
return KubeObjectMenuRegistry
|
||||||
.getInstance()
|
.getInstance()
|
||||||
.getItemsForKind(object.kind, object.apiVersion)
|
.getItemsForKind(object.kind, object.apiVersion)
|
||||||
.map(({components: { MenuItem }}, index) => (
|
.map(({ components: { MenuItem }}, index) => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
object={object}
|
object={object}
|
||||||
key={`menu-item-${index}`}
|
key={`menu-item-${index}`}
|
||||||
|
|||||||
@ -127,7 +127,7 @@ export class KubeConfigDialog extends React.Component<Props> {
|
|||||||
>
|
>
|
||||||
<Wizard header={header}>
|
<Wizard header={header}>
|
||||||
<WizardStep customButtons={buttons} prev={this.close}>
|
<WizardStep customButtons={buttons} prev={this.close}>
|
||||||
<MonacoEditor readOnly={true} value={yamlConfig}/>
|
<MonacoEditor readOnly={true} value={yamlConfig}/>
|
||||||
<textarea
|
<textarea
|
||||||
className="config-copy"
|
className="config-copy"
|
||||||
readOnly defaultValue={yamlConfig}
|
readOnly defaultValue={yamlConfig}
|
||||||
|
|||||||
@ -86,7 +86,7 @@ export class Sidebar extends React.Component<Props> {
|
|||||||
|
|
||||||
return Object.entries(crdStore.groups).map(([group, crds]) => {
|
return Object.entries(crdStore.groups).map(([group, crds]) => {
|
||||||
const id = `crd-group:${group}`;
|
const id = `crd-group:${group}`;
|
||||||
const crdGroupsPageUrl = routes.crdURL({ query: { groups: group } });
|
const crdGroupsPageUrl = routes.crdURL({ query: { groups: group }});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarItem key={id} id={id} text={group} url={crdGroupsPageUrl}>
|
<SidebarItem key={id} id={id} text={group} url={crdGroupsPageUrl}>
|
||||||
|
|||||||
@ -90,6 +90,10 @@ export class Menu extends React.Component<MenuProps, State> {
|
|||||||
return !!this.props.isOpen;
|
return !!this.props.isOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isClosed() {
|
||||||
|
return !this.isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (!this.props.usePortal) {
|
if (!this.props.usePortal) {
|
||||||
const parent = this.elem.parentElement;
|
const parent = this.elem.parentElement;
|
||||||
@ -202,19 +206,32 @@ export class Menu extends React.Component<MenuProps, State> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
open() {
|
open() {
|
||||||
if (this.isOpen) return;
|
if (this.isOpen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.props.open();
|
this.props.open();
|
||||||
this.refreshPosition();
|
this.refreshPosition();
|
||||||
if (this.props.autoFocus) this.focusNextItem();
|
|
||||||
|
if (this.props.autoFocus) {
|
||||||
|
this.focusNextItem();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
if (!this.isOpen) return;
|
if (this.isClosed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.props.close();
|
this.props.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle() {
|
toggle() {
|
||||||
this.isOpen ? this.close() : this.open();
|
if (this.isOpen) {
|
||||||
|
this.close();
|
||||||
|
} else {
|
||||||
|
this.open();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onKeyDown(evt: KeyboardEvent) {
|
onKeyDown(evt: KeyboardEvent) {
|
||||||
|
|||||||
@ -102,7 +102,7 @@ export function ReactTable({ columns, data, headless }: Props) {
|
|||||||
</div>}
|
</div>}
|
||||||
|
|
||||||
<div {...getTableBodyProps()}>
|
<div {...getTableBodyProps()}>
|
||||||
{rows.map((row, index) => RenderRow({index}))}
|
{rows.map((row, index) => RenderRow({ index }))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -85,7 +85,7 @@ export function RecursiveTreeView({ data }: Props) {
|
|||||||
nodeId={node.id}
|
nodeId={node.id}
|
||||||
label={node.name}
|
label={node.name}
|
||||||
onLabelClick={(event) => onLabelClick(event, node.id)}
|
onLabelClick={(event) => onLabelClick(event, node.id)}
|
||||||
className={cssNames({selected: node.selected})}
|
className={cssNames({ selected: node.selected })}
|
||||||
title={node.name}
|
title={node.name}
|
||||||
>
|
>
|
||||||
{Array.isArray(node.children) ? node.children.map((node) => renderTree([node])) : null}
|
{Array.isArray(node.children) ? node.children.map((node) => renderTree([node])) : null}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ export function initWelcomeMenuRegistry() {
|
|||||||
{
|
{
|
||||||
title: "Browse Clusters in Catalog",
|
title: "Browse Clusters in Catalog",
|
||||||
icon: "view_list",
|
icon: "view_list",
|
||||||
click: () => navigate(catalogURL({ params: { group: "entity.k8slens.dev", kind: "KubernetesCluster" } } )),
|
click: () => navigate(catalogURL({ params: { group: "entity.k8slens.dev", kind: "KubernetesCluster" }} )),
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ export function bindProtocolAddRouteHandlers() {
|
|||||||
.addInternalHandler("/landing", () => {
|
.addInternalHandler("/landing", () => {
|
||||||
navigate(routes.catalogURL());
|
navigate(routes.catalogURL());
|
||||||
})
|
})
|
||||||
.addInternalHandler("/landing/view/:group/:kind", ({ pathname: { group, kind } }) => {
|
.addInternalHandler("/landing/view/:group/:kind", ({ pathname: { group, kind }}) => {
|
||||||
navigate(routes.catalogURL({
|
navigate(routes.catalogURL({
|
||||||
params: {
|
params: {
|
||||||
group, kind
|
group, kind
|
||||||
@ -60,11 +60,11 @@ export function bindProtocolAddRouteHandlers() {
|
|||||||
.addInternalHandler("/cluster", () => {
|
.addInternalHandler("/cluster", () => {
|
||||||
navigate(routes.addClusterURL());
|
navigate(routes.addClusterURL());
|
||||||
})
|
})
|
||||||
.addInternalHandler("/entity/:entityId/settings", ({ pathname: { entityId } }) => {
|
.addInternalHandler("/entity/:entityId/settings", ({ pathname: { entityId }}) => {
|
||||||
const entity = catalogEntityRegistry.getById(entityId);
|
const entity = catalogEntityRegistry.getById(entityId);
|
||||||
|
|
||||||
if (entity) {
|
if (entity) {
|
||||||
navigate(routes.entitySettingsURL({ params: { entityId } }));
|
navigate(routes.entitySettingsURL({ params: { entityId }}));
|
||||||
} else {
|
} else {
|
||||||
Notifications.shortInfo(
|
Notifications.shortInfo(
|
||||||
<p>
|
<p>
|
||||||
@ -74,11 +74,11 @@ export function bindProtocolAddRouteHandlers() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Handlers below are deprecated and only kept for backward compact purposes
|
// Handlers below are deprecated and only kept for backward compact purposes
|
||||||
.addInternalHandler("/cluster/:clusterId", ({ pathname: { clusterId } }) => {
|
.addInternalHandler("/cluster/:clusterId", ({ pathname: { clusterId }}) => {
|
||||||
const cluster = ClusterStore.getInstance().getById(clusterId);
|
const cluster = ClusterStore.getInstance().getById(clusterId);
|
||||||
|
|
||||||
if (cluster) {
|
if (cluster) {
|
||||||
navigate(routes.clusterViewURL({ params: { clusterId } }));
|
navigate(routes.clusterViewURL({ params: { clusterId }}));
|
||||||
} else {
|
} else {
|
||||||
Notifications.shortInfo(
|
Notifications.shortInfo(
|
||||||
<p>
|
<p>
|
||||||
@ -87,11 +87,11 @@ export function bindProtocolAddRouteHandlers() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.addInternalHandler("/cluster/:clusterId/settings", ({ pathname: { clusterId } }) => {
|
.addInternalHandler("/cluster/:clusterId/settings", ({ pathname: { clusterId }}) => {
|
||||||
const cluster = ClusterStore.getInstance().getById(clusterId);
|
const cluster = ClusterStore.getInstance().getById(clusterId);
|
||||||
|
|
||||||
if (cluster) {
|
if (cluster) {
|
||||||
navigate(routes.entitySettingsURL({ params: { entityId: clusterId } }));
|
navigate(routes.entitySettingsURL({ params: { entityId: clusterId }}));
|
||||||
} else {
|
} else {
|
||||||
Notifications.shortInfo(
|
Notifications.shortInfo(
|
||||||
<p>
|
<p>
|
||||||
@ -103,7 +103,7 @@ export function bindProtocolAddRouteHandlers() {
|
|||||||
.addInternalHandler("/extensions", () => {
|
.addInternalHandler("/extensions", () => {
|
||||||
navigate(routes.extensionsURL());
|
navigate(routes.extensionsURL());
|
||||||
})
|
})
|
||||||
.addInternalHandler(`/extensions/install${LensProtocolRouter.ExtensionUrlSchema}`, ({ pathname, search: { version } }) => {
|
.addInternalHandler(`/extensions/install${LensProtocolRouter.ExtensionUrlSchema}`, ({ pathname, search: { version }}) => {
|
||||||
const name = [
|
const name = [
|
||||||
pathname[EXTENSION_PUBLISHER_MATCH],
|
pathname[EXTENSION_PUBLISHER_MATCH],
|
||||||
pathname[EXTENSION_NAME_MATCH],
|
pathname[EXTENSION_NAME_MATCH],
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export function interval(timeSec = 1, callback: IntervalCallback, autoRun = fals
|
|||||||
let timer = -1;
|
let timer = -1;
|
||||||
let isRunning = false;
|
let isRunning = false;
|
||||||
const intervalManager = {
|
const intervalManager = {
|
||||||
start (runImmediately = false) {
|
start(runImmediately = false) {
|
||||||
if (isRunning) return;
|
if (isRunning) return;
|
||||||
const tick = () => callback(++count);
|
const tick = () => callback(++count);
|
||||||
|
|
||||||
@ -36,12 +36,12 @@ export function interval(timeSec = 1, callback: IntervalCallback, autoRun = fals
|
|||||||
timer = window.setInterval(tick, 1000 * timeSec);
|
timer = window.setInterval(tick, 1000 * timeSec);
|
||||||
if (runImmediately) tick();
|
if (runImmediately) tick();
|
||||||
},
|
},
|
||||||
stop () {
|
stop() {
|
||||||
count = 0;
|
count = 0;
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
},
|
},
|
||||||
restart (runImmediately = false) {
|
restart(runImmediately = false) {
|
||||||
this.stop();
|
this.stop();
|
||||||
this.start(runImmediately);
|
this.start(runImmediately);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -28,7 +28,7 @@ import ProgressBarPlugin from "progress-bar-webpack-plugin";
|
|||||||
import * as vars from "./src/common/vars";
|
import * as vars from "./src/common/vars";
|
||||||
import getTSLoader from "./src/common/getTSLoader";
|
import getTSLoader from "./src/common/getTSLoader";
|
||||||
|
|
||||||
const configs: {(): webpack.Configuration}[] = [];
|
const configs: { (): webpack.Configuration }[] = [];
|
||||||
|
|
||||||
configs.push((): webpack.Configuration => {
|
configs.push((): webpack.Configuration => {
|
||||||
console.info("WEBPACK:main", vars);
|
console.info("WEBPACK:main", vars);
|
||||||
|
|||||||
16
yarn.lock
16
yarn.lock
@ -1856,10 +1856,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
|
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
|
||||||
integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
|
integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
|
||||||
|
|
||||||
"@types/spdy@^3.4.4":
|
"@types/spdy@^3.4.5":
|
||||||
version "3.4.4"
|
version "3.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/@types/spdy/-/spdy-3.4.4.tgz#3282fd4ad8c4603aa49f7017dd520a08a345b2bc"
|
resolved "https://registry.yarnpkg.com/@types/spdy/-/spdy-3.4.5.tgz#194dc132312ddcd31e8053789ae83a7bb32a8aaf"
|
||||||
integrity sha512-N9LBlbVRRYq6HgYpPkqQc3a9HJ/iEtVZToW6xlTtJiMhmRJ7jJdV7TaZQJw/Ve/1ePUsQiCTDc4JMuzzag94GA==
|
integrity sha512-/33fIRK/aqkKNxg9BSjpzt1ucmvPremgeDywm9z2C2mOlIh5Ljjvgc3UhQHqwXsSLDLHPT9jlsnrjKQ1XiVJzA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
@ -14602,10 +14602,10 @@ xterm-addon-fit@^0.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
|
resolved "https://registry.yarnpkg.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
|
||||||
integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==
|
integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==
|
||||||
|
|
||||||
xterm@^4.12.0:
|
xterm@^4.14.1:
|
||||||
version "4.12.0"
|
version "4.14.1"
|
||||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.12.0.tgz#db09b425b4dcae5b96f8cbbaaa93b3bc60997ca9"
|
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.14.1.tgz#6884cb8fb3b83353b1a98139ea23daedf8e35796"
|
||||||
integrity sha512-K5mF/p3txUV18mjiZFlElagoHFpqXrm5OYHeoymeXSu8GG/nMaOO/+NRcNCwfdjzAbdQ5VLF32hEHiWWKKm0bw==
|
integrity sha512-jgzNg5BuGPwq5/M4dGnmbghZvHx2jaj+9crSEt15bV34Za49VziBmCu7zIy88zUKKiGTxeo7aVzirFSJArIMFw==
|
||||||
|
|
||||||
y18n@^3.2.1:
|
y18n@^3.2.1:
|
||||||
version "3.2.2"
|
version "3.2.2"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user