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

Merge remote-tracking branch 'origin/master' into fix/catalog/icon_menu_option

# Conflicts:
#	src/renderer/components/+catalog/catalog.tsx
This commit is contained in:
Roman 2021-11-03 16:41:52 +02:00
commit 64765167eb
464 changed files with 2614 additions and 2170 deletions

View File

@ -31,18 +31,18 @@ module.exports = {
settings: { settings: {
react: { react: {
version: packageJson.devDependencies.react || "detect", version: packageJson.devDependencies.react || "detect",
} },
}, },
overrides: [ overrides: [
{ {
files: [ files: [
"**/*.js" "**/*.js",
], ],
extends: [ extends: [
"eslint:recommended", "eslint:recommended",
], ],
env: { env: {
node: true node: true,
}, },
parserOptions: { parserOptions: {
ecmaVersion: 2018, ecmaVersion: 2018,
@ -51,32 +51,44 @@ module.exports = {
plugins: [ plugins: [
"header", "header",
"unused-imports", "unused-imports",
"react-hooks" "react-hooks",
], ],
rules: { rules: {
"header/header": [2, "./license-header"], "header/header": [2, "./license-header"],
"comma-dangle": ["error", "always-multiline"],
"comma-spacing": "error",
"indent": ["error", 2, { "indent": ["error", 2, {
"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", {
"vars": "all", "vars": "all",
"args": "after-used", "args": "after-used",
"ignoreRestSiblings": true, "ignoreRestSiblings": true,
} },
], ],
"quotes": ["error", "double", { "quotes": ["error", "double", {
"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,9 +96,10 @@ 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",
},
}, },
{ {
files: [ files: [
@ -98,7 +111,7 @@ module.exports = {
], ],
plugins: [ plugins: [
"header", "header",
"unused-imports" "unused-imports",
], ],
parserOptions: { parserOptions: {
ecmaVersion: 2018, ecmaVersion: 2018,
@ -115,14 +128,24 @@ 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", {
"vars": "all", "vars": "all",
"args": "after-used", "args": "after-used",
"ignoreRestSiblings": true, "ignoreRestSiblings": true,
} },
], ],
"comman-dangle": "off",
"@typescript-eslint/comma-dangle": ["error", "always-multiline"],
"comma-spacing": "off",
"@typescript-eslint/comma-spacing": "error",
"indent": ["error", 2, { "indent": ["error", 2, {
"SwitchCase": 1, "SwitchCase": 1,
}], }],
@ -130,6 +153,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 +166,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 +175,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",
}, },
}, },
{ {
@ -156,7 +187,7 @@ module.exports = {
parser: "@typescript-eslint/parser", parser: "@typescript-eslint/parser",
plugins: [ plugins: [
"header", "header",
"unused-imports" "unused-imports",
], ],
extends: [ extends: [
"plugin:@typescript-eslint/recommended", "plugin:@typescript-eslint/recommended",
@ -183,14 +214,24 @@ 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", {
"vars": "all", "vars": "all",
"args": "after-used", "args": "after-used",
"ignoreRestSiblings": true, "ignoreRestSiblings": true,
} },
], ],
"comman-dangle": "off",
"@typescript-eslint/comma-dangle": ["error", "always-multiline"],
"comma-spacing": "off",
"@typescript-eslint/comma-spacing": "error",
"indent": ["error", 2, { "indent": ["error", 2, {
"SwitchCase": 1, "SwitchCase": 1,
}], }],
@ -198,6 +239,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 +252,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,11 +261,12 @@ 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",
}, },
} },
] ],
}; };

View File

@ -1,3 +1,3 @@
disturl "https://atom.io/download/electron" disturl "https://atom.io/download/electron"
target "13.6.0" target "13.6.1"
runtime "electron" runtime "electron"

View File

@ -36,7 +36,7 @@ dev: binaries/client build-extensions static/build/LensDev.html
yarn dev yarn dev
.PHONY: lint .PHONY: lint
lint: lint: node_modules
yarn lint yarn lint
.PHONY: tag-release .PHONY: tag-release

View File

@ -10,9 +10,9 @@ Lens releases are built by CICD automatically on git tags. The typical release p
- `major` - `major`
- `minor` - `minor`
- `patch` - `patch`
- `premajor` [--preid=<prerelease-id>] - `premajor [--preid=<prerelease-id>]`
- `preminor` [--preid=<prerelease-id>] - `preminor [--preid=<prerelease-id>]`
- `prepatch` [--preid=<prerelease-id>] - `prepatch [--preid=<prerelease-id>]`
- `prerelease [--preid=<prerelease-id>]` - `prerelease [--preid=<prerelease-id>]`
where `<prerelease-id>` is generally one of: where `<prerelease-id>` is generally one of:
@ -28,6 +28,8 @@ Lens releases are built by CICD automatically on git tags. The typical release p
- `git tag -fa vX.Y.Z-beta.N` (move the tag locally to the current commit) - `git tag -fa vX.Y.Z-beta.N` (move the tag locally to the current commit)
- `git push origin --tags` (update the tags on https://github.com/lensapp/lens to reflect this local change) - `git push origin --tags` (update the tags on https://github.com/lensapp/lens to reflect this local change)
Once the tag has been updated on origin (e.g. by `git push origin --tags`) the azure jobs are automatically triggered again.
1. Once CI passes again go to the releases tab on GitHub. You can use the existing draft release prepared by k8slens-bot (select the correct tag). Or you can create a new release from the tag that was created, and make sure that the change log is the same as that of the PR, and the title is the tag. Either way, click the prerelease checkbox if this is not a new major, minor, or patch version before clicking `Publish release`. 1. Once CI passes again go to the releases tab on GitHub. You can use the existing draft release prepared by k8slens-bot (select the correct tag). Or you can create a new release from the tag that was created, and make sure that the change log is the same as that of the PR, and the title is the tag. Either way, click the prerelease checkbox if this is not a new major, minor, or patch version before clicking `Publish release`.
1. Merge the release PR after the release is published. If it is a patch release then there is no need to squash the cherry-picked commits as part of the merge. GitHub should delete the branch once it is merged. 1. Merge the release PR after the release is published. If it is a patch release then there is no need to squash the cherry-picked commits as part of the merge. GitHub should delete the branch once it is merged.
1. If you have just released a new major or minor version then create a new `release/vMAJOR.MINOR` branch from that same tag and push it to https://github.com/lensapp/lens. Given the commit of the merged release PR from the master branch you can do this like 1. If you have just released a new major or minor version then create a new `release/vMAJOR.MINOR` branch from that same tag and push it to https://github.com/lensapp/lens. Given the commit of the merged release PR from the master branch you can do this like

View File

@ -28,6 +28,6 @@ export default {
}, },
dialog: jest.fn(), dialog: jest.fn(),
ipcRenderer: { ipcRenderer: {
on: jest.fn() on: jest.fn(),
} },
}; };

View File

@ -28,7 +28,7 @@ const helmVersion = packageInfo.config.bundledHelmVersion;
if (!isWindows) { if (!isWindows) {
Promise.all([ Promise.all([
new HelmCli(path.join(process.cwd(), "binaries", "client", "x64"), helmVersion).ensureBinary(), new HelmCli(path.join(process.cwd(), "binaries", "client", "x64"), helmVersion).ensureBinary(),
new HelmCli(path.join(process.cwd(), "binaries", "client", "arm64"), helmVersion).ensureBinary() new HelmCli(path.join(process.cwd(), "binaries", "client", "arm64"), helmVersion).ensureBinary(),
]); ]);
} else { } else {
new HelmCli(path.join(process.cwd(), "binaries", "client", "x64"), helmVersion).ensureBinary(); new HelmCli(path.join(process.cwd(), "binaries", "client", "x64"), helmVersion).ensureBinary();

View File

@ -47,7 +47,7 @@ class KubectlDownloader {
const response = await requestPromise({ const response = await requestPromise({
method: "HEAD", method: "HEAD",
uri: this.url, uri: this.url,
resolveWithFullResponse: true resolveWithFullResponse: true,
}).catch(console.error); }).catch(console.error);
if (response.headers["etag"]) { if (response.headers["etag"]) {
@ -89,7 +89,7 @@ class KubectlDownloader {
console.log(`Downloading kubectl ${this.kubectlVersion} from ${this.url} to ${this.path}`); console.log(`Downloading kubectl ${this.kubectlVersion} from ${this.url} to ${this.path}`);
const requestOpts: request.UriOptions & request.CoreOptions = { const requestOpts: request.UriOptions & request.CoreOptions = {
uri: this.url, uri: this.url,
gzip: true gzip: true,
}; };
const stream = request(requestOpts); const stream = request(requestOpts);

View File

@ -27,37 +27,37 @@ export default class EventResourceStatusRendererExtension extends Renderer.LensE
{ {
kind: "Pod", kind: "Pod",
apiVersions: ["v1"], apiVersions: ["v1"],
resolve: (pod: Renderer.K8sApi.Pod) => resolveStatusForPods(pod) resolve: (pod: Renderer.K8sApi.Pod) => resolveStatusForPods(pod),
}, },
{ {
kind: "ReplicaSet", kind: "ReplicaSet",
apiVersions: ["v1"], apiVersions: ["v1"],
resolve: (replicaSet: Renderer.K8sApi.ReplicaSet) => resolveStatus(replicaSet) resolve: (replicaSet: Renderer.K8sApi.ReplicaSet) => resolveStatus(replicaSet),
}, },
{ {
kind: "Deployment", kind: "Deployment",
apiVersions: ["apps/v1"], apiVersions: ["apps/v1"],
resolve: (deployment: Renderer.K8sApi.Deployment) => resolveStatus(deployment) resolve: (deployment: Renderer.K8sApi.Deployment) => resolveStatus(deployment),
}, },
{ {
kind: "StatefulSet", kind: "StatefulSet",
apiVersions: ["apps/v1"], apiVersions: ["apps/v1"],
resolve: (statefulSet: Renderer.K8sApi.StatefulSet) => resolveStatus(statefulSet) resolve: (statefulSet: Renderer.K8sApi.StatefulSet) => resolveStatus(statefulSet),
}, },
{ {
kind: "DaemonSet", kind: "DaemonSet",
apiVersions: ["apps/v1"], apiVersions: ["apps/v1"],
resolve: (daemonSet: Renderer.K8sApi.DaemonSet) => resolveStatus(daemonSet) resolve: (daemonSet: Renderer.K8sApi.DaemonSet) => resolveStatus(daemonSet),
}, },
{ {
kind: "Job", kind: "Job",
apiVersions: ["batch/v1"], apiVersions: ["batch/v1"],
resolve: (job: Renderer.K8sApi.Job) => resolveStatus(job) resolve: (job: Renderer.K8sApi.Job) => resolveStatus(job),
}, },
{ {
kind: "CronJob", kind: "CronJob",
apiVersions: ["batch/v1"], apiVersions: ["batch/v1"],
resolve: (cronJob: Renderer.K8sApi.CronJob) => resolveStatusForCronJobs(cronJob) resolve: (cronJob: Renderer.K8sApi.CronJob) => resolveStatusForCronJobs(cronJob),
}, },
]; ];
} }

View File

@ -42,7 +42,7 @@ export function resolveStatus(object: KubeObject): KubeObjectStatus {
return { return {
level: KubeObjectStatusLevel.WARNING, level: KubeObjectStatusLevel.WARNING,
text: `${event.message}`, text: `${event.message}`,
timestamp: event.metadata.creationTimestamp timestamp: event.metadata.creationTimestamp,
}; };
} }
@ -62,7 +62,7 @@ export function resolveStatusForPods(pod: Pod): KubeObjectStatus {
return { return {
level: KubeObjectStatusLevel.WARNING, level: KubeObjectStatusLevel.WARNING,
text: `${event.message}`, text: `${event.message}`,
timestamp: event.metadata.creationTimestamp timestamp: event.metadata.creationTimestamp,
}; };
} }
@ -83,6 +83,6 @@ export function resolveStatusForCronJobs(cronJob: CronJob): KubeObjectStatus {
return { return {
level: KubeObjectStatusLevel.WARNING, level: KubeObjectStatusLevel.WARNING,
text: `${event.message}`, text: `${event.message}`,
timestamp: event.metadata.creationTimestamp timestamp: event.metadata.creationTimestamp,
}; };
} }

View File

@ -27,7 +27,7 @@ module.exports = [
target: "electron-renderer", target: "electron-renderer",
mode: "production", mode: "production",
optimization: { optimization: {
minimize: false minimize: false,
}, },
module: { module: {
rules: [ rules: [
@ -43,8 +43,8 @@ module.exports = [
"@k8slens/extensions": "var global.LensExtensions", "@k8slens/extensions": "var global.LensExtensions",
"react": "var global.React", "react": "var global.React",
"mobx": "var global.Mobx", "mobx": "var global.Mobx",
"mobx-react": "var global.MobxReact" "mobx-react": "var global.MobxReact",
} },
], ],
resolve: { resolve: {
extensions: [ ".tsx", ".ts", ".js" ], extensions: [ ".tsx", ".ts", ".js" ],

View File

@ -31,12 +31,12 @@ 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} />
); );
} },
} },
} },
]; ];
} }

View File

@ -31,6 +31,13 @@ rules:
verbs: verbs:
- list - list
- watch - watch
- apiGroups:
- networking.k8s.io
resources:
- ingresses
verbs:
- list
- watch
- apiGroups: - apiGroups:
- apps - apps
resources: resources:

View File

@ -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";

View File

@ -30,7 +30,7 @@ const {
}, },
Component: { Component: {
SubTitle, FormSwitch, Switcher, Button, SubTitle, FormSwitch, Switcher, Button,
} },
} = Renderer; } = Renderer;
interface Props { interface Props {
@ -47,7 +47,7 @@ export class MetricsSettings extends React.Component<Props> {
@observable featureStates = { @observable featureStates = {
prometheus: false, prometheus: false,
kubeStateMetrics: false, kubeStateMetrics: false,
nodeExporter: false nodeExporter: false,
}; };
@observable canUpgrade = false; @observable canUpgrade = false;
@observable upgrading = false; @observable upgrading = false;
@ -56,7 +56,7 @@ export class MetricsSettings extends React.Component<Props> {
config: MetricsConfiguration = { config: MetricsConfiguration = {
prometheus: { prometheus: {
enabled: false enabled: false,
}, },
persistence: { persistence: {
enabled: false, enabled: false,
@ -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 &quot;Metrics&quot; tab for details. Other metrics provider is currently active. See &quot;Metrics&quot; tab for details.
</p> </p>
</section> </section>

View File

@ -27,7 +27,7 @@ module.exports = [
target: "electron-renderer", target: "electron-renderer",
mode: "production", mode: "production",
optimization: { optimization: {
minimize: false minimize: false,
}, },
module: { module: {
rules: [ rules: [
@ -43,8 +43,8 @@ module.exports = [
"@k8slens/extensions": "var global.LensExtensions", "@k8slens/extensions": "var global.LensExtensions",
"react": "var global.React", "react": "var global.React",
"mobx": "var global.Mobx", "mobx": "var global.Mobx",
"mobx-react": "var global.MobxReact" "mobx-react": "var global.MobxReact",
} },
], ],
resolve: { resolve: {
extensions: [ ".tsx", ".ts", ".js" ], extensions: [ ".tsx", ".ts", ".js" ],
@ -56,7 +56,7 @@ module.exports = [
path: path.resolve(__dirname, "dist"), path: path.resolve(__dirname, "dist"),
}, },
node: { node: {
__dirname: false __dirname: false,
} },
}, },
]; ];

View File

@ -29,8 +29,8 @@ export default class NodeMenuRendererExtension extends Renderer.LensExtension {
kind: "Node", kind: "Node",
apiVersions: ["v1"], apiVersions: ["v1"],
components: { components: {
MenuItem: (props: NodeMenuProps) => <NodeMenu {...props} /> MenuItem: (props: NodeMenuProps) => <NodeMenu {...props} />,
} },
} },
]; ];
} }

View File

@ -20,7 +20,7 @@
*/ */
import React from "react"; import React from "react";
import { Renderer } from "@k8slens/extensions"; import { Common, Renderer } from "@k8slens/extensions";
type Node = Renderer.K8sApi.Node; type Node = Renderer.K8sApi.Node;
@ -32,8 +32,11 @@ const {
MenuItem, MenuItem,
Icon, Icon,
}, },
Navigation Navigation,
} = Renderer; } = Renderer;
const {
App,
} = Common;
export interface NodeMenuProps extends Renderer.Component.KubeObjectMenuProps<Node> { export interface NodeMenuProps extends Renderer.Component.KubeObjectMenuProps<Node> {
@ -42,8 +45,12 @@ export interface NodeMenuProps extends Renderer.Component.KubeObjectMenuProps<No
export function NodeMenu(props: NodeMenuProps) { export function NodeMenu(props: NodeMenuProps) {
const { object: node, toolbar } = props; const { object: node, toolbar } = props;
if (!node) return null; if (!node) {
return null;
}
const nodeName = node.getName(); const nodeName = node.getName();
const kubectlPath = App.Preferences.getKubectlPath() || "kubectl";
const sendToTerminal = (command: string) => { const sendToTerminal = (command: string) => {
terminalStore.sendCommand(command, { terminalStore.sendCommand(command, {
@ -62,15 +69,15 @@ export function NodeMenu(props: NodeMenuProps) {
}; };
const cordon = () => { const cordon = () => {
sendToTerminal(`kubectl cordon ${nodeName}`); sendToTerminal(`${kubectlPath} cordon ${nodeName}`);
}; };
const unCordon = () => { const unCordon = () => {
sendToTerminal(`kubectl uncordon ${nodeName}`); sendToTerminal(`${kubectlPath} uncordon ${nodeName}`);
}; };
const drain = () => { const drain = () => {
const command = `kubectl drain ${nodeName} --delete-local-data --ignore-daemonsets --force`; const command = `${kubectlPath} drain ${nodeName} --delete-local-data --ignore-daemonsets --force`;
ConfirmDialog.open({ ConfirmDialog.open({
ok: () => sendToTerminal(command), ok: () => sendToTerminal(command),

View File

@ -27,7 +27,7 @@ module.exports = [
target: "electron-renderer", target: "electron-renderer",
mode: "production", mode: "production",
optimization: { optimization: {
minimize: false minimize: false,
}, },
module: { module: {
rules: [ rules: [
@ -43,8 +43,8 @@ module.exports = [
"@k8slens/extensions": "var global.LensExtensions", "@k8slens/extensions": "var global.LensExtensions",
"react": "var global.React", "react": "var global.React",
"mobx": "var global.Mobx", "mobx": "var global.Mobx",
"mobx-react": "var global.MobxReact" "mobx-react": "var global.MobxReact",
} },
], ],
resolve: { resolve: {
extensions: [ ".tsx", ".ts", ".js" ], extensions: [ ".tsx", ".ts", ".js" ],

View File

@ -31,22 +31,22 @@ export default class PodMenuRendererExtension extends Renderer.LensExtension {
kind: "Pod", kind: "Pod",
apiVersions: ["v1"], apiVersions: ["v1"],
components: { components: {
MenuItem: (props: PodAttachMenuProps) => <PodAttachMenu {...props} /> MenuItem: (props: PodAttachMenuProps) => <PodAttachMenu {...props} />,
} },
}, },
{ {
kind: "Pod", kind: "Pod",
apiVersions: ["v1"], apiVersions: ["v1"],
components: { components: {
MenuItem: (props: PodShellMenuProps) => <PodShellMenu {...props} /> MenuItem: (props: PodShellMenuProps) => <PodShellMenu {...props} />,
} },
}, },
{ {
kind: "Pod", kind: "Pod",
apiVersions: ["v1"], apiVersions: ["v1"],
components: { components: {
MenuItem: (props: PodLogsMenuProps) => <PodLogsMenu {...props} /> MenuItem: (props: PodLogsMenuProps) => <PodLogsMenu {...props} />,
} },
} },
]; ];
} }

View File

@ -39,6 +39,7 @@ const {
} = Renderer; } = Renderer;
const { const {
Util, Util,
App,
} = Common; } = Common;
export interface PodAttachMenuProps extends Renderer.Component.KubeObjectMenuProps<Pod> { export interface PodAttachMenuProps extends Renderer.Component.KubeObjectMenuProps<Pod> {
@ -47,22 +48,34 @@ export interface PodAttachMenuProps extends Renderer.Component.KubeObjectMenuPro
export class PodAttachMenu extends React.Component<PodAttachMenuProps> { export class PodAttachMenu extends React.Component<PodAttachMenuProps> {
async attachToPod(container?: string) { async attachToPod(container?: string) {
const { object: pod } = this.props; const { object: pod } = this.props;
const containerParam = container ? `-c ${container}` : "";
let command = `kubectl attach -i -t -n ${pod.getNs()} ${pod.getName()} ${containerParam}`; const kubectlPath = App.Preferences.getKubectlPath() || "kubectl";
const commandParts = [
kubectlPath,
"attach",
"-i",
"-t",
"-n", pod.getNs(),
pod.getName(),
];
if (window.navigator.platform !== "Win32") { if (window.navigator.platform !== "Win32") {
command = `exec ${command}`; commandParts.unshift("exec");
}
if (container) {
commandParts.push("-c", container);
} }
const shell = createTerminalTab({ const shell = createTerminalTab({
title: `Pod: ${pod.getName()} (namespace: ${pod.getNs()}) [Attached]` title: `Pod: ${pod.getName()} (namespace: ${pod.getNs()}) [Attached]`,
}); });
terminalStore.sendCommand(command, { terminalStore.sendCommand(commandParts.join(" "), {
enter: true, enter: true,
tabId: shell.id tabId: shell.id,
}); });
Navigation.hideDetails(); Navigation.hideDetails();
} }

View File

@ -39,6 +39,7 @@ const {
} = Renderer; } = Renderer;
const { const {
Util, Util,
App,
} = Common; } = Common;
export interface PodShellMenuProps extends Renderer.Component.KubeObjectMenuProps<Pod> { export interface PodShellMenuProps extends Renderer.Component.KubeObjectMenuProps<Pod> {
@ -46,29 +47,44 @@ export interface PodShellMenuProps extends Renderer.Component.KubeObjectMenuProp
export class PodShellMenu extends React.Component<PodShellMenuProps> { export class PodShellMenu extends React.Component<PodShellMenuProps> {
async execShell(container?: string) { async execShell(container?: string) {
Navigation.hideDetails();
const { object: pod } = this.props; const { object: pod } = this.props;
const containerParam = container ? `-c ${container}` : "";
let command = `kubectl exec -i -t -n ${pod.getNs()} ${pod.getName()} ${containerParam} "--"`; const kubectlPath = App.Preferences.getKubectlPath() || "kubectl";
const commandParts = [
kubectlPath,
"exec",
"-i",
"-t",
"-n", pod.getNs(),
pod.getName(),
];
if (window.navigator.platform !== "Win32") { if (window.navigator.platform !== "Win32") {
command = `exec ${command}`; commandParts.unshift("exec");
} }
if (container) {
commandParts.push("-c", container);
}
commandParts.push("--");
if (pod.getSelectedNodeOs() === "windows") { if (pod.getSelectedNodeOs() === "windows") {
command = `${command} powershell`; commandParts.push("powershell");
} else { } else {
command = `${command} sh -c "clear; (bash || ash || sh)"`; commandParts.push('sh -c "clear; (bash || ash || sh)"');
} }
const shell = createTerminalTab({ const shell = createTerminalTab({
title: `Pod: ${pod.getName()} (namespace: ${pod.getNs()})` title: `Pod: ${pod.getName()} (namespace: ${pod.getNs()})`,
}); });
terminalStore.sendCommand(command, { terminalStore.sendCommand(commandParts.join(" "), {
enter: true, enter: true,
tabId: shell.id tabId: shell.id,
}); });
Navigation.hideDetails();
} }
render() { render() {

View File

@ -27,7 +27,7 @@ module.exports = [
target: "electron-renderer", target: "electron-renderer",
mode: "production", mode: "production",
optimization: { optimization: {
minimize: false minimize: false,
}, },
module: { module: {
rules: [ rules: [
@ -43,8 +43,8 @@ module.exports = [
"@k8slens/extensions": "var global.LensExtensions", "@k8slens/extensions": "var global.LensExtensions",
"react": "var global.React", "react": "var global.React",
"mobx": "var global.Mobx", "mobx": "var global.Mobx",
"mobx-react": "var global.MobxReact" "mobx-react": "var global.MobxReact",
} },
], ],
resolve: { resolve: {
extensions: [ ".tsx", ".ts", ".js" ], extensions: [ ".tsx", ".ts", ".js" ],

View File

@ -75,16 +75,16 @@ const commonPageTests: CommonPageTest[] = [{
name: "Cluster", name: "Cluster",
href: "/overview", href: "/overview",
expectedSelector: "div[data-testid='cluster-overview-page'] div.label", expectedSelector: "div[data-testid='cluster-overview-page'] div.label",
expectedText: "CPU" expectedText: "CPU",
} },
}, },
{ {
page: { page: {
name: "Nodes", name: "Nodes",
href: "/nodes", href: "/nodes",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Nodes" expectedText: "Nodes",
} },
}, },
{ {
drawerId: "workloads", drawerId: "workloads",
@ -93,51 +93,51 @@ const commonPageTests: CommonPageTest[] = [{
name: "Overview", name: "Overview",
href: "/workloads", href: "/workloads",
expectedSelector: "h5.box", expectedSelector: "h5.box",
expectedText: "Overview" expectedText: "Overview",
}, },
{ {
name: "Pods", name: "Pods",
href: "/pods", href: "/pods",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Pods" expectedText: "Pods",
}, },
{ {
name: "Deployments", name: "Deployments",
href: "/deployments", href: "/deployments",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Deployments" expectedText: "Deployments",
}, },
{ {
name: "DaemonSets", name: "DaemonSets",
href: "/daemonsets", href: "/daemonsets",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Daemon Sets" expectedText: "Daemon Sets",
}, },
{ {
name: "StatefulSets", name: "StatefulSets",
href: "/statefulsets", href: "/statefulsets",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Stateful Sets" expectedText: "Stateful Sets",
}, },
{ {
name: "ReplicaSets", name: "ReplicaSets",
href: "/replicasets", href: "/replicasets",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Replica Sets" expectedText: "Replica Sets",
}, },
{ {
name: "Jobs", name: "Jobs",
href: "/jobs", href: "/jobs",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Jobs" expectedText: "Jobs",
}, },
{ {
name: "CronJobs", name: "CronJobs",
href: "/cronjobs", href: "/cronjobs",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Cron Jobs" expectedText: "Cron Jobs",
}, },
] ],
}, },
{ {
drawerId: "config", drawerId: "config",
@ -146,39 +146,39 @@ const commonPageTests: CommonPageTest[] = [{
name: "ConfigMaps", name: "ConfigMaps",
href: "/configmaps", href: "/configmaps",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Config Maps" expectedText: "Config Maps",
}, },
{ {
name: "Secrets", name: "Secrets",
href: "/secrets", href: "/secrets",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Secrets" expectedText: "Secrets",
}, },
{ {
name: "Resource Quotas", name: "Resource Quotas",
href: "/resourcequotas", href: "/resourcequotas",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Resource Quotas" expectedText: "Resource Quotas",
}, },
{ {
name: "Limit Ranges", name: "Limit Ranges",
href: "/limitranges", href: "/limitranges",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Limit Ranges" expectedText: "Limit Ranges",
}, },
{ {
name: "HPA", name: "HPA",
href: "/hpa", href: "/hpa",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Horizontal Pod Autoscalers" expectedText: "Horizontal Pod Autoscalers",
}, },
{ {
name: "Pod Disruption Budgets", name: "Pod Disruption Budgets",
href: "/poddisruptionbudgets", href: "/poddisruptionbudgets",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Pod Disruption Budgets" expectedText: "Pod Disruption Budgets",
}, },
] ],
}, },
{ {
drawerId: "networks", drawerId: "networks",
@ -187,27 +187,27 @@ const commonPageTests: CommonPageTest[] = [{
name: "Services", name: "Services",
href: "/services", href: "/services",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Services" expectedText: "Services",
}, },
{ {
name: "Endpoints", name: "Endpoints",
href: "/endpoints", href: "/endpoints",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Endpoints" expectedText: "Endpoints",
}, },
{ {
name: "Ingresses", name: "Ingresses",
href: "/ingresses", href: "/ingresses",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Ingresses" expectedText: "Ingresses",
}, },
{ {
name: "Network Policies", name: "Network Policies",
href: "/network-policies", href: "/network-policies",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Network Policies" expectedText: "Network Policies",
}, },
] ],
}, },
{ {
drawerId: "storage", drawerId: "storage",
@ -216,37 +216,37 @@ const commonPageTests: CommonPageTest[] = [{
name: "Persistent Volume Claims", name: "Persistent Volume Claims",
href: "/persistent-volume-claims", href: "/persistent-volume-claims",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Persistent Volume Claims" expectedText: "Persistent Volume Claims",
}, },
{ {
name: "Persistent Volumes", name: "Persistent Volumes",
href: "/persistent-volumes", href: "/persistent-volumes",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Persistent Volumes" expectedText: "Persistent Volumes",
}, },
{ {
name: "Storage Classes", name: "Storage Classes",
href: "/storage-classes", href: "/storage-classes",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Storage Classes" expectedText: "Storage Classes",
}, },
] ],
}, },
{ {
page: { page: {
name: "Namespaces", name: "Namespaces",
href: "/namespaces", href: "/namespaces",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Namespaces" expectedText: "Namespaces",
} },
}, },
{ {
page: { page: {
name: "Events", name: "Events",
href: "/events", href: "/events",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Events" expectedText: "Events",
} },
}, },
{ {
drawerId: "apps", drawerId: "apps",
@ -260,9 +260,9 @@ const commonPageTests: CommonPageTest[] = [{
name: "Releases", name: "Releases",
href: "/apps/releases", href: "/apps/releases",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Releases" expectedText: "Releases",
}, },
] ],
}, },
{ {
drawerId: "users", drawerId: "users",
@ -271,39 +271,39 @@ const commonPageTests: CommonPageTest[] = [{
name: "Service Accounts", name: "Service Accounts",
href: "/service-accounts", href: "/service-accounts",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Service Accounts" expectedText: "Service Accounts",
}, },
{ {
name: "Roles", name: "Roles",
href: "/roles", href: "/roles",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Roles" expectedText: "Roles",
}, },
{ {
name: "Cluster Roles", name: "Cluster Roles",
href: "/cluster-roles", href: "/cluster-roles",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Cluster Roles" expectedText: "Cluster Roles",
}, },
{ {
name: "Role Bindings", name: "Role Bindings",
href: "/role-bindings", href: "/role-bindings",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Role Bindings" expectedText: "Role Bindings",
}, },
{ {
name: "Cluster Role Bindings", name: "Cluster Role Bindings",
href: "/cluster-role-bindings", href: "/cluster-role-bindings",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Cluster Role Bindings" expectedText: "Cluster Role Bindings",
}, },
{ {
name: "Pod Security Policies", name: "Pod Security Policies",
href: "/pod-security-policies", href: "/pod-security-policies",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Pod Security Policies" expectedText: "Pod Security Policies",
}, },
] ],
}, },
{ {
drawerId: "custom-resources", drawerId: "custom-resources",
@ -312,9 +312,9 @@ const commonPageTests: CommonPageTest[] = [{
name: "Definitions", name: "Definitions",
href: "/crd/definitions", href: "/crd/definitions",
expectedSelector: "h5.title", expectedSelector: "h5.title",
expectedText: "Custom Resources" expectedText: "Custom Resources",
}, },
] ],
}]; }];
utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => { utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
@ -440,7 +440,7 @@ utils.describeIf(minikubeReady(TEST_NAMESPACE))("Minikube based tests", () => {
position: { position: {
y: 0, y: 0,
x: 0, x: 0,
} },
}); });
} catch (error) { } catch (error) {
console.log(error); console.log(error);

View File

@ -69,7 +69,7 @@ export async function start() {
bypassCSP: true, bypassCSP: true,
env: { env: {
CICD, CICD,
...process.env ...process.env,
}, },
timeout: 100_000, timeout: 100_000,
} as Parameters<typeof electron["launch"]>[0]); } as Parameters<typeof electron["launch"]>[0]);

View File

@ -3,7 +3,7 @@
"productName": "OpenLens", "productName": "OpenLens",
"description": "OpenLens - Open Source IDE for Kubernetes", "description": "OpenLens - Open Source IDE for Kubernetes",
"homepage": "https://github.com/lensapp/lens", "homepage": "https://github.com/lensapp/lens",
"version": "5.3.0-alpha.6", "version": "5.3.0-alpha.8",
"main": "static/build/main.js", "main": "static/build/main.js",
"copyright": "© 2021 OpenLens Authors", "copyright": "© 2021 OpenLens Authors",
"license": "MIT", "license": "MIT",
@ -196,7 +196,7 @@
"electron-devtools-installer": "^3.2.0", "electron-devtools-installer": "^3.2.0",
"electron-updater": "^4.6.1", "electron-updater": "^4.6.1",
"electron-window-state": "^5.0.3", "electron-window-state": "^5.0.3",
"filehound": "^1.17.4", "filehound": "^1.17.5",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"got": "^11.8.2", "got": "^11.8.2",
@ -214,12 +214,12 @@
"md5-file": "^5.0.0", "md5-file": "^5.0.0",
"mobx": "^6.3.0", "mobx": "^6.3.0",
"mobx-observable-history": "^2.0.1", "mobx-observable-history": "^2.0.1",
"mobx-react": "^7.2.0", "mobx-react": "^7.2.1",
"mock-fs": "^4.14.0", "mock-fs": "^4.14.0",
"moment": "^2.29.1", "moment": "^2.29.1",
"moment-timezone": "^0.5.33", "moment-timezone": "^0.5.33",
"monaco-editor": "^0.26.1", "monaco-editor": "^0.26.1",
"node-fetch": "^2.6.5", "node-fetch": "^2.6.6",
"node-pty": "^0.10.1", "node-pty": "^0.10.1",
"npm": "^6.14.15", "npm": "^6.14.15",
"p-limit": "^3.1.0", "p-limit": "^3.1.0",
@ -255,9 +255,8 @@
"@material-ui/lab": "^4.0.0-alpha.60", "@material-ui/lab": "^4.0.0-alpha.60",
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3", "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
"@sentry/types": "^6.13.3", "@sentry/types": "^6.13.3",
"@testing-library/dom": "^8.9.0", "@testing-library/jest-dom": "^5.15.0",
"@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^11.2.7",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"@types/byline": "^4.2.33", "@types/byline": "^4.2.33",
"@types/chart.js": "^2.9.34", "@types/chart.js": "^2.9.34",
@ -285,10 +284,10 @@
"@types/progress-bar-webpack-plugin": "^2.1.2", "@types/progress-bar-webpack-plugin": "^2.1.2",
"@types/proper-lockfile": "^4.1.2", "@types/proper-lockfile": "^4.1.2",
"@types/randomcolor": "^0.5.6", "@types/randomcolor": "^0.5.6",
"@types/react": "^17.0.29", "@types/react": "^17.0.33",
"@types/react-beautiful-dnd": "^13.1.2", "@types/react-beautiful-dnd": "^13.1.2",
"@types/react-dom": "^17.0.9", "@types/react-dom": "^17.0.9",
"@types/react-router-dom": "^5.3.1", "@types/react-router-dom": "^5.3.2",
"@types/react-select": "3.1.2", "@types/react-select": "3.1.2",
"@types/react-table": "^7.7.7", "@types/react-table": "^7.7.7",
"@types/react-virtualized-auto-sizer": "^1.0.1", "@types/react-virtualized-auto-sizer": "^1.0.1",
@ -296,9 +295,9 @@
"@types/readable-stream": "^2.3.11", "@types/readable-stream": "^2.3.11",
"@types/request": "^2.48.7", "@types/request": "^2.48.7",
"@types/request-promise-native": "^1.0.18", "@types/request-promise-native": "^1.0.18",
"@types/semver": "^7.2.0", "@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",
@ -310,7 +309,7 @@
"@types/webpack-env": "^1.16.3", "@types/webpack-env": "^1.16.3",
"@types/webpack-node-externals": "^1.7.1", "@types/webpack-node-externals": "^1.7.1",
"@typescript-eslint/eslint-plugin": "^4.33.0", "@typescript-eslint/eslint-plugin": "^4.33.0",
"@typescript-eslint/parser": "^4.29.1", "@typescript-eslint/parser": "^4.33.0",
"ansi_up": "^5.0.1", "ansi_up": "^5.0.1",
"chart.js": "^2.9.4", "chart.js": "^2.9.4",
"circular-dependency-plugin": "^5.2.2", "circular-dependency-plugin": "^5.2.2",
@ -319,7 +318,7 @@
"css-loader": "^5.2.7", "css-loader": "^5.2.7",
"deepdash": "^5.3.9", "deepdash": "^5.3.9",
"dompurify": "^2.3.3", "dompurify": "^2.3.3",
"electron": "13.6.0", "electron": "^13.6.1",
"electron-builder": "^22.11.11", "electron-builder": "^22.11.11",
"electron-notarize": "^0.3.0", "electron-notarize": "^0.3.0",
"esbuild": "^0.13.8", "esbuild": "^0.13.8",
@ -345,7 +344,7 @@
"node-loader": "^1.0.3", "node-loader": "^1.0.3",
"nodemon": "^2.0.14", "nodemon": "^2.0.14",
"playwright": "^1.15.2", "playwright": "^1.15.2",
"postcss": "^8.3.6", "postcss": "^8.3.11",
"postcss-loader": "4.3.0", "postcss-loader": "4.3.0",
"postinstall-postinstall": "^2.1.0", "postinstall-postinstall": "^2.1.0",
"progress-bar-webpack-plugin": "^2.1.0", "progress-bar-webpack-plugin": "^2.1.0",
@ -357,17 +356,17 @@
"react-select": "3.2.0", "react-select": "3.2.0",
"react-select-event": "^5.1.0", "react-select-event": "^5.1.0",
"react-table": "^7.7.0", "react-table": "^7.7.0",
"react-window": "^1.8.5", "react-window": "^1.8.6",
"sass": "^1.43.2", "sass": "^1.43.4",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
"sharp": "^0.29.2", "sharp": "^0.29.2",
"style-loader": "^2.0.0", "style-loader": "^2.0.0",
"tailwindcss": "^2.2.17", "tailwindcss": "^2.2.17",
"ts-jest": "26.5.6", "ts-jest": "26.5.6",
"ts-loader": "^7.0.5", "ts-loader": "^7.0.5",
"ts-node": "^10.3.0", "ts-node": "^10.4.0",
"type-fest": "^1.0.2", "type-fest": "^1.0.2",
"typed-emitter": "^1.3.1", "typed-emitter": "^1.4.0",
"typedoc": "0.22.7", "typedoc": "0.22.7",
"typedoc-plugin-markdown": "^3.11.3", "typedoc-plugin-markdown": "^3.11.3",
"typeface-roboto": "^1.1.13", "typeface-roboto": "^1.1.13",
@ -379,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"
} }
} }

View File

@ -34,8 +34,8 @@ class TestCatalogCategory extends CatalogCategory {
group: "entity.k8slens.dev", group: "entity.k8slens.dev",
versions: [], versions: [],
names: { names: {
kind: "Test" kind: "Test",
} },
}; };
} }
@ -50,8 +50,8 @@ class TestCatalogCategory2 extends CatalogCategory {
group: "entity.k8slens.dev", group: "entity.k8slens.dev",
versions: [], versions: [],
names: { names: {
kind: "Test2" kind: "Test2",
} },
}; };
} }

View File

@ -84,7 +84,7 @@ jest.mock("electron", () => ({
removeAllListeners: jest.fn(), removeAllListeners: jest.fn(),
off: jest.fn(), off: jest.fn(),
send: jest.fn(), send: jest.fn(),
} },
})); }));
AppPaths.init(); AppPaths.init();
@ -95,8 +95,8 @@ describe("empty config", () => {
ClusterStore.resetInstance(); ClusterStore.resetInstance();
const mockOpts = { const mockOpts = {
"tmp": { "tmp": {
"lens-cluster-store.json": JSON.stringify({}) "lens-cluster-store.json": JSON.stringify({}),
} },
}; };
mockFs(mockOpts); mockFs(mockOpts);
@ -117,10 +117,10 @@ describe("empty config", () => {
preferences: { preferences: {
terminalCWD: "/tmp", terminalCWD: "/tmp",
icon: "data:image/jpeg;base64, iVBORw0KGgoAAAANSUhEUgAAA1wAAAKoCAYAAABjkf5", icon: "data:image/jpeg;base64, iVBORw0KGgoAAAANSUhEUgAAA1wAAAKoCAYAAABjkf5",
clusterName: "minikube" clusterName: "minikube",
}, },
kubeConfigPath: embed("foo", kubeconfig) kubeConfigPath: embed("foo", kubeconfig),
}) }),
); );
}); });
@ -141,17 +141,17 @@ describe("empty config", () => {
id: "prod", id: "prod",
contextName: "foo", contextName: "foo",
preferences: { preferences: {
clusterName: "prod" clusterName: "prod",
}, },
kubeConfigPath: embed("prod", kubeconfig) kubeConfigPath: embed("prod", kubeconfig),
}); });
store.addCluster({ store.addCluster({
id: "dev", id: "dev",
contextName: "foo2", contextName: "foo2",
preferences: { preferences: {
clusterName: "dev" clusterName: "dev",
}, },
kubeConfigPath: embed("dev", kubeconfig) kubeConfigPath: embed("dev", kubeconfig),
}); });
}); });
@ -177,8 +177,8 @@ describe("config with existing clusters", () => {
"lens-cluster-store.json": JSON.stringify({ "lens-cluster-store.json": JSON.stringify({
__internal__: { __internal__: {
migrations: { migrations: {
version: "99.99.99" version: "99.99.99",
} },
}, },
clusters: [ clusters: [
{ {
@ -186,13 +186,13 @@ describe("config with existing clusters", () => {
kubeConfigPath: "./temp-kube-config", kubeConfigPath: "./temp-kube-config",
contextName: "foo", contextName: "foo",
preferences: { terminalCWD: "/foo" }, preferences: { terminalCWD: "/foo" },
workspace: "default" workspace: "default",
}, },
{ {
id: "cluster2", id: "cluster2",
kubeConfigPath: "./temp-kube-config", kubeConfigPath: "./temp-kube-config",
contextName: "foo2", contextName: "foo2",
preferences: { terminalCWD: "/foo2" } preferences: { terminalCWD: "/foo2" },
}, },
{ {
id: "cluster3", id: "cluster3",
@ -200,11 +200,11 @@ describe("config with existing clusters", () => {
contextName: "foo", contextName: "foo",
preferences: { terminalCWD: "/foo" }, preferences: { terminalCWD: "/foo" },
workspace: "foo", workspace: "foo",
ownerRef: "foo" ownerRef: "foo",
}, },
] ],
}) }),
} },
}; };
mockFs(mockOpts); mockFs(mockOpts);
@ -265,8 +265,8 @@ users:
"lens-cluster-store.json": JSON.stringify({ "lens-cluster-store.json": JSON.stringify({
__internal__: { __internal__: {
migrations: { migrations: {
version: "99.99.99" version: "99.99.99",
} },
}, },
clusters: [ clusters: [
{ {
@ -281,12 +281,12 @@ users:
kubeConfigPath: "./valid-kube-config", kubeConfigPath: "./valid-kube-config",
contextName: "foo", contextName: "foo",
preferences: { terminalCWD: "/foo" }, preferences: { terminalCWD: "/foo" },
workspace: "default" workspace: "default",
}, },
] ],
}) }),
} },
}; };
mockFs(mockOpts); mockFs(mockOpts);
@ -326,7 +326,7 @@ const minimalValidKubeConfig = JSON.stringify({
user: { user: {
"client-certificate": "/Users/foo/.minikube/client.crt", "client-certificate": "/Users/foo/.minikube/client.crt",
"client-key": "/Users/foo/.minikube/client.key", "client-key": "/Users/foo/.minikube/client.key",
} },
}], }],
kind: "Config", kind: "Config",
preferences: {}, preferences: {},
@ -340,12 +340,12 @@ describe("pre 2.0 config with an existing cluster", () => {
"lens-cluster-store.json": JSON.stringify({ "lens-cluster-store.json": JSON.stringify({
__internal__: { __internal__: {
migrations: { migrations: {
version: "1.0.0" version: "1.0.0",
} },
}, },
cluster1: minimalValidKubeConfig, cluster1: minimalValidKubeConfig,
}) }),
} },
}; };
mockFs(mockOpts); mockFs(mockOpts);
@ -372,8 +372,8 @@ describe("pre 2.6.0 config with a cluster that has arrays in auth config", () =>
"lens-cluster-store.json": JSON.stringify({ "lens-cluster-store.json": JSON.stringify({
__internal__: { __internal__: {
migrations: { migrations: {
version: "2.4.1" version: "2.4.1",
} },
}, },
cluster1: { cluster1: {
kubeConfig: JSON.stringify({ kubeConfig: JSON.stringify({
@ -403,19 +403,19 @@ describe("pre 2.6.0 config with a cluster that has arrays in auth config", () =>
"auth-provider": { "auth-provider": {
config: { config: {
"access-token": [ "access-token": [
"should be string" "should be string",
], ],
expiry: [ expiry: [
"should be string" "should be string",
], ],
} },
} },
}, },
}] }],
}), }),
}, },
}) }),
} },
}; };
mockFs(mockOpts); mockFs(mockOpts);
@ -445,19 +445,19 @@ describe("pre 2.6.0 config with a cluster icon", () => {
"lens-cluster-store.json": JSON.stringify({ "lens-cluster-store.json": JSON.stringify({
__internal__: { __internal__: {
migrations: { migrations: {
version: "2.4.1" version: "2.4.1",
} },
}, },
cluster1: { cluster1: {
kubeConfig: minimalValidKubeConfig, kubeConfig: minimalValidKubeConfig,
icon: "icon_path", icon: "icon_path",
preferences: { preferences: {
terminalCWD: "/tmp" terminalCWD: "/tmp",
} },
}, },
}), }),
"icon_path": testDataIcon, "icon_path": testDataIcon,
} },
}; };
mockFs(mockOpts); mockFs(mockOpts);
@ -486,17 +486,17 @@ describe("for a pre 2.7.0-beta.0 config without a workspace", () => {
"lens-cluster-store.json": JSON.stringify({ "lens-cluster-store.json": JSON.stringify({
__internal__: { __internal__: {
migrations: { migrations: {
version: "2.6.6" version: "2.6.6",
} },
}, },
cluster1: { cluster1: {
kubeConfig: minimalValidKubeConfig, kubeConfig: minimalValidKubeConfig,
preferences: { preferences: {
terminalCWD: "/tmp" terminalCWD: "/tmp",
} },
}, },
}) }),
} },
}; };
mockFs(mockOpts); mockFs(mockOpts);
@ -517,8 +517,8 @@ describe("pre 3.6.0-beta.1 config with an existing cluster", () => {
"lens-cluster-store.json": JSON.stringify({ "lens-cluster-store.json": JSON.stringify({
__internal__: { __internal__: {
migrations: { migrations: {
version: "3.5.0" version: "3.5.0",
} },
}, },
clusters: [ clusters: [
{ {
@ -527,12 +527,12 @@ describe("pre 3.6.0-beta.1 config with an existing cluster", () => {
contextName: "cluster", contextName: "cluster",
preferences: { preferences: {
icon: "store://icon_path", icon: "store://icon_path",
} },
} },
] ],
}), }),
"icon_path": testDataIcon, "icon_path": testDataIcon,
} },
}; };
mockFs(mockOpts); mockFs(mockOpts);

View File

@ -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");
}); });
}); });

View File

@ -33,25 +33,25 @@ jest.mock("../../main/catalog/catalog-entity-registry", () => ({
metadata: { metadata: {
uid: "1dfa26e2ebab15780a3547e9c7fa785c", uid: "1dfa26e2ebab15780a3547e9c7fa785c",
name: "mycluster", name: "mycluster",
source: "local" source: "local",
} },
}, },
{ {
metadata: { metadata: {
uid: "55b42c3c7ba3b04193416cda405269a5", uid: "55b42c3c7ba3b04193416cda405269a5",
name: "my_shiny_cluster", name: "my_shiny_cluster",
source: "remote" source: "remote",
} },
}, },
{ {
metadata: { metadata: {
uid: "catalog-entity", uid: "catalog-entity",
name: "Catalog", name: "Catalog",
source: "app" source: "app",
}, },
}, },
] ],
} },
})); }));
const testCluster = { const testCluster = {
@ -60,7 +60,7 @@ const testCluster = {
apiVersion: "v1", apiVersion: "v1",
kind: "Cluster", kind: "Cluster",
status: { status: {
phase: "Running" phase: "Running",
}, },
spec: {}, spec: {},
getName: jest.fn(), getName: jest.fn(),
@ -71,8 +71,8 @@ const testCluster = {
metadata: { metadata: {
uid: "test", uid: "test",
name: "test", name: "test",
labels: {} labels: {},
} },
}; };
const minikubeCluster = { const minikubeCluster = {
@ -81,7 +81,7 @@ const minikubeCluster = {
apiVersion: "v1", apiVersion: "v1",
kind: "Cluster", kind: "Cluster",
status: { status: {
phase: "Running" phase: "Running",
}, },
spec: {}, spec: {},
getName: jest.fn(), getName: jest.fn(),
@ -92,8 +92,8 @@ const minikubeCluster = {
metadata: { metadata: {
uid: "minikube", uid: "minikube",
name: "minikube", name: "minikube",
labels: {} labels: {},
} },
}; };
const awsCluster = { const awsCluster = {
@ -102,7 +102,7 @@ const awsCluster = {
apiVersion: "v1", apiVersion: "v1",
kind: "Cluster", kind: "Cluster",
status: { status: {
phase: "Running" phase: "Running",
}, },
spec: {}, spec: {},
getName: jest.fn(), getName: jest.fn(),
@ -113,8 +113,8 @@ const awsCluster = {
metadata: { metadata: {
uid: "aws", uid: "aws",
name: "aws", name: "aws",
labels: {} labels: {},
} },
}; };
jest.mock("electron", () => ({ jest.mock("electron", () => ({
@ -139,8 +139,8 @@ describe("HotbarStore", () => {
beforeEach(() => { beforeEach(() => {
mockFs({ mockFs({
"tmp": { "tmp": {
"lens-hotbar-store.json": JSON.stringify({}) "lens-hotbar-store.json": JSON.stringify({}),
} },
}); });
ClusterStore.createInstance(); ClusterStore.createInstance();
HotbarStore.createInstance(); HotbarStore.createInstance();
@ -351,8 +351,8 @@ describe("HotbarStore", () => {
"lens-hotbar-store.json": JSON.stringify({ "lens-hotbar-store.json": JSON.stringify({
__internal__: { __internal__: {
migrations: { migrations: {
version: "5.0.0-beta.3" version: "5.0.0-beta.3",
} },
}, },
"hotbars": [ "hotbars": [
{ {
@ -361,51 +361,51 @@ describe("HotbarStore", () => {
"items": [ "items": [
{ {
"entity": { "entity": {
"uid": "1dfa26e2ebab15780a3547e9c7fa785c" "uid": "1dfa26e2ebab15780a3547e9c7fa785c",
} },
}, },
{ {
"entity": { "entity": {
"uid": "55b42c3c7ba3b04193416cda405269a5" "uid": "55b42c3c7ba3b04193416cda405269a5",
} },
}, },
{ {
"entity": { "entity": {
"uid": "176fd331968660832f62283219d7eb6e" "uid": "176fd331968660832f62283219d7eb6e",
} },
}, },
{ {
"entity": { "entity": {
"uid": "61c4fb45528840ebad1badc25da41d14", "uid": "61c4fb45528840ebad1badc25da41d14",
"name": "user1-context", "name": "user1-context",
"source": "local" "source": "local",
} },
}, },
{ {
"entity": { "entity": {
"uid": "27d6f99fe9e7548a6e306760bfe19969", "uid": "27d6f99fe9e7548a6e306760bfe19969",
"name": "foo2", "name": "foo2",
"source": "local" "source": "local",
} },
}, },
null, null,
{ {
"entity": { "entity": {
"uid": "c0b20040646849bb4dcf773e43a0bf27", "uid": "c0b20040646849bb4dcf773e43a0bf27",
"name": "multinode-demo", "name": "multinode-demo",
"source": "local" "source": "local",
} },
}, },
null, null,
null, null,
null, null,
null, null,
null null,
] ],
} },
], ],
}) }),
} },
}; };
mockFs(mockOpts); mockFs(mockOpts);
@ -436,16 +436,16 @@ describe("HotbarStore", () => {
entity: { entity: {
name: "mycluster", name: "mycluster",
source: "local", source: "local",
uid: "1dfa26e2ebab15780a3547e9c7fa785c" uid: "1dfa26e2ebab15780a3547e9c7fa785c",
} },
}); });
expect(items[1]).toEqual({ expect(items[1]).toEqual({
entity: { entity: {
name: "my_shiny_cluster", name: "my_shiny_cluster",
source: "remote", source: "remote",
uid: "55b42c3c7ba3b04193416cda405269a5" uid: "55b42c3c7ba3b04193416cda405269a5",
} },
}); });
}); });
}); });

View File

@ -100,7 +100,7 @@ describe("kube helpers", () => {
describe("with invalid context object", () => { describe("with invalid context object", () => {
it("returns an error", () => { it("returns an error", () => {
expect(String(validateKubeConfig(kc, "invalid"))).toEqual( expect(String(validateKubeConfig(kc, "invalid"))).toEqual(
expect.stringContaining("No valid context object provided in kubeconfig for context 'invalid'") expect.stringContaining("No valid context object provided in kubeconfig for context 'invalid'"),
); );
}); });
}); });
@ -108,7 +108,7 @@ describe("kube helpers", () => {
describe("with invalid cluster object", () => { describe("with invalid cluster object", () => {
it("returns an error", () => { it("returns an error", () => {
expect(String(validateKubeConfig(kc, "invalidCluster"))).toEqual( expect(String(validateKubeConfig(kc, "invalidCluster"))).toEqual(
expect.stringContaining("No valid cluster object provided in kubeconfig for context 'invalidCluster'") expect.stringContaining("No valid cluster object provided in kubeconfig for context 'invalidCluster'"),
); );
}); });
}); });
@ -116,7 +116,7 @@ describe("kube helpers", () => {
describe("with invalid user object", () => { describe("with invalid user object", () => {
it("returns an error", () => { it("returns an error", () => {
expect(String(validateKubeConfig(kc, "invalidUser"))).toEqual( expect(String(validateKubeConfig(kc, "invalidUser"))).toEqual(
expect.stringContaining("No valid user object provided in kubeconfig for context 'invalidUser'") expect.stringContaining("No valid user object provided in kubeconfig for context 'invalidUser'"),
); );
}); });
}); });
@ -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));

View File

@ -37,7 +37,7 @@ let searchStore: SearchStore = null;
const logs = [ const logs = [
"1:M 30 Oct 2020 16:17:41.553 # Connection with replica 172.17.0.12:6379 lost", "1:M 30 Oct 2020 16:17:41.553 # Connection with replica 172.17.0.12:6379 lost",
"1:M 30 Oct 2020 16:17:41.623 * Replica 172.17.0.12:6379 asks for synchronization", "1:M 30 Oct 2020 16:17:41.623 * Replica 172.17.0.12:6379 asks for synchronization",
"1:M 30 Oct 2020 16:17:41.623 * Starting Partial resynchronization request from 172.17.0.12:6379 accepted. Sending 0 bytes of backlog starting from offset 14407." "1:M 30 Oct 2020 16:17:41.623 * Starting Partial resynchronization request from 172.17.0.12:6379 accepted. Sending 0 bytes of backlog starting from offset 14407.",
]; ];
describe("search store tests", () => { describe("search store tests", () => {

View File

@ -0,0 +1,113 @@
/**
* Copyright (c) 2021 OpenLens Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import https from "https";
import os from "os";
import { getMacRootCA, getWinRootCA, injectCAs, DSTRootCAX3 } from "../system-ca";
import { dependencies, devDependencies } from "../../../package.json";
const deps = { ...dependencies, ...devDependencies };
// Skip the test if mac-ca is not installed, or os is not darwin
(deps["mac-ca"] && os.platform().includes("darwin") ? describe: describe.skip)("inject CA for Mac", () => {
// for reset https.globalAgent.options.ca after testing
let _ca: string | Buffer | (string | Buffer)[];
beforeEach(() => {
_ca = https.globalAgent.options.ca;
});
afterEach(() => {
https.globalAgent.options.ca = _ca;
});
/**
* The test to ensure using getMacRootCA + injectCAs injects CAs in the same way as using
* the auto injection (require('mac-ca'))
*/
it("should inject the same ca as mac-ca", async () => {
const osxCAs = await getMacRootCA();
injectCAs(osxCAs);
const injected = https.globalAgent.options.ca as (string | Buffer)[];
await import("mac-ca");
const injectedByMacCA = https.globalAgent.options.ca as (string | Buffer)[];
expect(new Set(injected)).toEqual(new Set(injectedByMacCA));
});
it("shouldn't included the expired DST Root CA X3 on Mac", async () => {
const osxCAs = await getMacRootCA();
injectCAs(osxCAs);
const injected = https.globalAgent.options.ca;
expect(injected.includes(DSTRootCAX3)).toBeFalsy();
});
});
// Skip the test if win-ca is not installed, or os is not win32
(deps["win-ca"] && os.platform().includes("win32") ? describe: describe.skip)("inject CA for Windows", () => {
// for reset https.globalAgent.options.ca after testing
let _ca: string | Buffer | (string | Buffer)[];
beforeEach(() => {
_ca = https.globalAgent.options.ca;
});
afterEach(() => {
https.globalAgent.options.ca = _ca;
});
/**
* The test to ensure using win-ca/api injects CAs in the same way as using
* the auto injection (require('win-ca').inject('+'))
*/
it("should inject the same ca as winca.inject('+')", async () => {
const winCAs = await getWinRootCA();
const wincaAPI = await import("win-ca/api");
wincaAPI.inject("+", winCAs);
const injected = https.globalAgent.options.ca as (string | Buffer)[];
const winca = await import("win-ca");
winca.inject("+"); // see: https://github.com/ukoloff/win-ca#caveats
const injectedByWinCA = https.globalAgent.options.ca as (string | Buffer)[];
expect(new Set(injected)).toEqual(new Set(injectedByWinCA));
});
it("shouldn't included the expired DST Root CA X3 on Windows", async () => {
const winCAs = await getWinRootCA();
const wincaAPI = await import("win-ca/api");
wincaAPI.inject("true", winCAs);
const injected = https.globalAgent.options.ca as (string | Buffer)[];
expect(injected.includes(DSTRootCAX3)).toBeFalsy();
});
});

View File

@ -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());
}); });
@ -106,7 +106,7 @@ describe("user store tests", () => {
"config.json": JSON.stringify({ "config.json": JSON.stringify({
user: { username: "foobar" }, user: { username: "foobar" },
preferences: { colorTheme: "light" }, preferences: { colorTheme: "light" },
lastSeenAppVersion: "1.2.3" lastSeenAppVersion: "1.2.3",
}), }),
"lens-cluster-store.json": JSON.stringify({ "lens-cluster-store.json": JSON.stringify({
clusters: [ clusters: [
@ -118,15 +118,15 @@ describe("user store tests", () => {
id: "barfoo", id: "barfoo",
kubeConfigPath: "some/other/path", kubeConfigPath: "some/other/path",
}, },
] ],
} as ClusterStoreModel), } as ClusterStoreModel),
"extension_data": {}, "extension_data": {},
}, },
"some": { "some": {
"other": { "other": {
"path": "is file", "path": "is file",
} },
} },
}); });
UserStore.createInstance(); UserStore.createInstance();

View File

@ -26,13 +26,13 @@ describe("kubernetesClusterCategory", () => {
icon: "Icon", icon: "Icon",
title: "Title", title: "Title",
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
onClick: () => {} onClick: () => {},
}; };
const item2 = { const item2 = {
icon: "Icon 2", icon: "Icon 2",
title: "Title 2", title: "Title 2",
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
onClick: () => {} onClick: () => {},
}; };
it("returns all items if no filter set", () => { it("returns all items if no filter set", () => {

View File

@ -57,19 +57,19 @@ export class GeneralCategory extends CatalogCategory {
public readonly kind = "CatalogCategory"; public readonly kind = "CatalogCategory";
public metadata = { public metadata = {
name: "General", name: "General",
icon: "settings" icon: "settings",
}; };
public spec = { public spec = {
group: "entity.k8slens.dev", group: "entity.k8slens.dev",
versions: [ versions: [
{ {
name: "v1alpha1", name: "v1alpha1",
entityClass: GeneralEntity entityClass: GeneralEntity,
} },
], ],
names: { names: {
kind: "General" kind: "General",
} },
}; };
} }

View File

@ -59,7 +59,7 @@ export enum LensKubernetesClusterStatus {
DELETING = "deleting", DELETING = "deleting",
CONNECTING = "connecting", CONNECTING = "connecting",
CONNECTED = "connected", CONNECTED = "connected",
DISCONNECTED = "disconnected" DISCONNECTED = "disconnected",
} }
export interface KubernetesClusterMetadata extends CatalogEntityMetadata { export interface KubernetesClusterMetadata extends CatalogEntityMetadata {
@ -128,14 +128,14 @@ export class KubernetesCluster extends CatalogEntity<KubernetesClusterMetadata,
context.menuItems.push({ context.menuItems.push({
title: "Disconnect", title: "Disconnect",
icon: "link_off", icon: "link_off",
onClick: () => requestMain(clusterDisconnectHandler, this.metadata.uid) onClick: () => requestMain(clusterDisconnectHandler, this.metadata.uid),
}); });
break; break;
case LensKubernetesClusterStatus.DISCONNECTED: case LensKubernetesClusterStatus.DISCONNECTED:
context.menuItems.push({ context.menuItems.push({
title: "Connect", title: "Connect",
icon: "link", icon: "link",
onClick: () => context.navigate(`/cluster/${this.metadata.uid}`) onClick: () => context.navigate(`/cluster/${this.metadata.uid}`),
}); });
break; break;
} }
@ -158,12 +158,12 @@ class KubernetesClusterCategory extends CatalogCategory {
versions: [ versions: [
{ {
name: "v1alpha1", name: "v1alpha1",
entityClass: KubernetesCluster entityClass: KubernetesCluster,
} },
], ],
names: { names: {
kind: "KubernetesCluster" kind: "KubernetesCluster",
} },
}; };
} }

View File

@ -56,8 +56,8 @@ export class WebLink extends CatalogEntity<CatalogEntityMetadata, WebLinkStatus,
icon: "delete", icon: "delete",
onClick: async () => WeblinkStore.getInstance().removeById(this.metadata.uid), onClick: async () => WeblinkStore.getInstance().removeById(this.metadata.uid),
confirm: { confirm: {
message: `Remove Web Link "${this.metadata.name}" from ${productName}?` message: `Remove Web Link "${this.metadata.name}" from ${productName}?`,
} },
}); });
} }
@ -72,19 +72,19 @@ export class WebLinkCategory extends CatalogCategory {
public readonly kind = "CatalogCategory"; public readonly kind = "CatalogCategory";
public metadata = { public metadata = {
name: "Web Links", name: "Web Links",
icon: "public" icon: "public",
}; };
public spec = { public spec = {
group: "entity.k8slens.dev", group: "entity.k8slens.dev",
versions: [ versions: [
{ {
name: "v1alpha1", name: "v1alpha1",
entityClass: WebLink entityClass: WebLink,
} },
], ],
names: { names: {
kind: "WebLink" kind: "WebLink",
} },
}; };
public static onAdd?: () => void; public static onAdd?: () => void;
@ -97,7 +97,7 @@ export class WebLinkCategory extends CatalogCategory {
title: "Add web link", title: "Add web link",
onClick: () => { onClick: () => {
WebLinkCategory.onAdd(); WebLinkCategory.onAdd();
} },
}); });
}); });
} }

View File

@ -59,7 +59,7 @@ export class CatalogCategoryRegistry {
this.filters, this.filters,
iter.filter, iter.filter,
this.items.values(), this.items.values(),
) ),
); );
} }

View File

@ -106,7 +106,7 @@ export abstract class CatalogCategory extends (EventEmitter as new () => TypedEm
this.filters, this.filters,
iter.filter, iter.filter,
menuItems.values(), menuItems.values(),
) ),
); );
} }
} }

View File

@ -119,7 +119,7 @@ export interface ClusterPrometheusPreferences {
export enum ClusterStatus { export enum ClusterStatus {
AccessGranted = 2, AccessGranted = 2,
AccessDenied = 1, AccessDenied = 1,
Offline = 0 Offline = 0,
} }
/** /**
@ -131,7 +131,7 @@ export enum ClusterMetadataKey {
DISTRIBUTION = "distribution", DISTRIBUTION = "distribution",
NODES_COUNT = "nodes", NODES_COUNT = "nodes",
LAST_SEEN = "lastSeen", LAST_SEEN = "lastSeen",
PROMETHEUS = "prometheus" PROMETHEUS = "prometheus",
} }
/** /**

View File

@ -23,27 +23,25 @@ import esbuild from "esbuild";
/** /**
* A function returning webpack ts/tsx loader * A function returning webpack ts/tsx loader
* *
* depends on env LENS_DEV_USE_ESBUILD_LOADER to use esbuild-loader (faster) or good-old ts-loader * depends on env LENS_DEV_USE_ESBUILD_LOADER to use esbuild-loader (faster) or good-old ts-loader
* *
* @param testRegExp - the regex for webpack to conditional find the files * @param testRegExp - the regex for webpack to conditional find the files
* @returns ts/tsx webpack loader configuration object * @returns ts/tsx webpack loader configuration object
*/ */
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",
options: { options: {
loader: "tsx", loader: "tsx",
target: "es2015", target: "es2015",
implementation: esbuild implementation: esbuild,
}, },
}; };
} }
@ -55,8 +53,8 @@ const getTSLoader = (
loader: "ts-loader", loader: "ts-loader",
options: { options: {
transpileOnly, transpileOnly,
} },
} },
}; };
}; };

View File

@ -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;
@ -99,7 +99,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
toJSON(): HotbarStoreModel { toJSON(): HotbarStoreModel {
const model: HotbarStoreModel = { const model: HotbarStoreModel = {
hotbars: this.hotbars, hotbars: this.hotbars,
activeHotbarId: this.activeHotbarId activeHotbarId: this.activeHotbarId,
}; };
return toJS(model); return toJS(model);
@ -187,7 +187,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
} else if (0 <= cellIndex && cellIndex < hotbar.items.length) { } else if (0 <= cellIndex && cellIndex < hotbar.items.length) {
hotbar.items[cellIndex] = newItem; hotbar.items[cellIndex] = newItem;
} else { } else {
logger.error(`[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range`, { entityId: uid, hotbarId: hotbar.id, cellIndex, }); logger.error(`[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range`, { entityId: uid, hotbarId: hotbar.id, cellIndex });
} }
} }

View File

@ -49,20 +49,20 @@ function getSubFrames(): ClusterFrameInfo[] {
} }
export function broadcastMessage(channel: string, ...args: any[]) { export function broadcastMessage(channel: string, ...args: any[]) {
const views: undefined | ReturnType<typeof webContents.getAllWebContents> | ReturnType<typeof remote.webContents.getAllWebContents> = (webContents || electronRemote?.webContents)?.getAllWebContents();
if (!views || !Array.isArray(views) || views.length === 0) return;
args = args.map(sanitizePayload);
ipcRenderer?.send(channel, ...args);
ipcMain?.emit(channel, ...args);
const subFramesP = ipcRenderer const subFramesP = ipcRenderer
? requestMain(subFramesChannel) ? requestMain(subFramesChannel)
: Promise.resolve(getSubFrames()); : Promise.resolve(getSubFrames());
subFramesP subFramesP
.then(subFrames => { .then(subFrames => {
const views: undefined | ReturnType<typeof webContents.getAllWebContents> | ReturnType<typeof remote.webContents.getAllWebContents> = (webContents || electronRemote?.webContents)?.getAllWebContents();
if (!views || !Array.isArray(views) || views.length === 0) return;
args = args.map(sanitizePayload);
ipcRenderer?.send(channel, ...args);
ipcMain?.emit(channel, ...args);
for (const view of views) { for (const view of views) {
let viewType = "unknown"; let viewType = "unknown";

View File

@ -38,7 +38,7 @@ export type Rest<T> = T extends [any, ...infer R] ? R : [];
*/ */
export function onceCorrect< export function onceCorrect<
IPC extends EventEmitter, IPC extends EventEmitter,
Listener extends (event: ListenerEvent<IPC>, ...args: any[]) => any Listener extends (event: ListenerEvent<IPC>, ...args: any[]) => any,
>({ >({
source, source,
channel, channel,
@ -72,7 +72,7 @@ export function onceCorrect<
*/ */
export function onCorrect< export function onCorrect<
IPC extends EventEmitter, IPC extends EventEmitter,
Listener extends (event: ListenerEvent<IPC>, ...args: any[]) => any Listener extends (event: ListenerEvent<IPC>, ...args: any[]) => any,
>({ >({
source, source,
channel, channel,

View File

@ -119,7 +119,7 @@ describe("Crds", () => {
}, },
spec: { spec: {
version: "abc", version: "abc",
} },
}); });
expect(crd.getVersion()).toBe("abc"); expect(crd.getVersion()).toBe("abc");

View File

@ -41,19 +41,19 @@ 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: {
spec: { spec: {
replicas: 5 replicas: 5,
} },
} },
}, },
{ {
headers: { headers: {
"content-type": "application/merge-patch+json" "content-type": "application/merge-patch+json",
} },
}); });
}); });
}); });

View File

@ -282,7 +282,7 @@ describe("HelmChart tests", () => {
expect(warnFn).toHaveBeenCalledWith("HelmChart data has unexpected fields", { expect(warnFn).toHaveBeenCalledWith("HelmChart data has unexpected fields", {
original: anyObject(), original: anyObject(),
unknownFields: ["asdjhajksdhadjks"] unknownFields: ["asdjhajksdhadjks"],
}); });
console.warn = warn; console.warn = warn;
}); });

View File

@ -26,7 +26,7 @@ jest.mock("../api-manager", () => ({
return { return {
registerStore: jest.fn(), registerStore: jest.fn(),
}; };
} },
})); }));
import { IKubeApiParsed, parseKubeApi } from "../kube-api-parse"; import { IKubeApiParsed, parseKubeApi } from "../kube-api-parse";
@ -45,7 +45,7 @@ const tests: KubeApiParseTestData[] = [
apiVersionWithGroup: "apiextensions.k8s.io/v1beta1", apiVersionWithGroup: "apiextensions.k8s.io/v1beta1",
namespace: undefined, namespace: undefined,
resource: "customresourcedefinitions", resource: "customresourcedefinitions",
name: "prometheuses.monitoring.coreos.com" name: "prometheuses.monitoring.coreos.com",
}], }],
["/api/v1/namespaces/kube-system/pods/coredns-6955765f44-v8p27", { ["/api/v1/namespaces/kube-system/pods/coredns-6955765f44-v8p27", {
apiBase: "/api/v1/pods", apiBase: "/api/v1/pods",
@ -55,7 +55,7 @@ const tests: KubeApiParseTestData[] = [
apiVersionWithGroup: "v1", apiVersionWithGroup: "v1",
namespace: "kube-system", namespace: "kube-system",
resource: "pods", resource: "pods",
name: "coredns-6955765f44-v8p27" name: "coredns-6955765f44-v8p27",
}], }],
["/apis/stable.example.com/foo1/crontabs", { ["/apis/stable.example.com/foo1/crontabs", {
apiBase: "/apis/stable.example.com/foo1/crontabs", apiBase: "/apis/stable.example.com/foo1/crontabs",
@ -132,7 +132,7 @@ const tests: KubeApiParseTestData[] = [
const throwtests = [ const throwtests = [
undefined, undefined,
"", "",
"ajklsmh" "ajklsmh",
]; ];
describe("parseApi unit tests", () => { describe("parseApi unit tests", () => {

View File

@ -28,11 +28,11 @@ describe("forRemoteCluster", () => {
it("builds api client", async (done) => { it("builds api client", async (done) => {
const api = forRemoteCluster({ const api = forRemoteCluster({
cluster: { cluster: {
server: "https://127.0.0.1:6443" server: "https://127.0.0.1:6443",
}, },
user: { user: {
token: "daa" token: "daa",
} },
}, Pod); }, Pod);
(fetch as any).mockResponse(async (request: any) => { (fetch as any).mockResponse(async (request: any) => {
@ -41,7 +41,7 @@ describe("forRemoteCluster", () => {
done(); done();
return { return {
body: "" body: "",
}; };
}); });
@ -55,7 +55,7 @@ describe("KubeApi", () => {
beforeEach(() => { beforeEach(() => {
request = new KubeJsonApi({ request = new KubeJsonApi({
serverAddress: `http://127.0.0.1:9999`, serverAddress: `http://127.0.0.1:9999`,
apiBase: "/api-kube" apiBase: "/api-kube",
}); });
}); });
@ -65,24 +65,24 @@ describe("KubeApi", () => {
return { return {
body: JSON.stringify({ body: JSON.stringify({
resources: [{ resources: [{
name: "ingresses" name: "ingresses",
}] as any[] }] as any[],
}) }),
}; };
} else if (request.url === "http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1") { } else if (request.url === "http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1") {
// Even if the old API contains ingresses, KubeApi should prefer the apiBase url // Even if the old API contains ingresses, KubeApi should prefer the apiBase url
return { return {
body: JSON.stringify({ body: JSON.stringify({
resources: [{ resources: [{
name: "ingresses" name: "ingresses",
}] as any[] }] as any[],
}) }),
}; };
} else { } else {
return { return {
body: JSON.stringify({ body: JSON.stringify({
resources: [] as any[] resources: [] as any[],
}) }),
}; };
} }
}); });
@ -107,22 +107,22 @@ describe("KubeApi", () => {
if (request.url === "http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1") { if (request.url === "http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1") {
return { return {
body: JSON.stringify({ body: JSON.stringify({
resources: [] as any[] resources: [] as any[],
}) }),
}; };
} else if (request.url === "http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1") { } else if (request.url === "http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1") {
return { return {
body: JSON.stringify({ body: JSON.stringify({
resources: [{ resources: [{
name: "ingresses" name: "ingresses",
}] as any[] }] as any[],
}) }),
}; };
} else { } else {
return { return {
body: JSON.stringify({ body: JSON.stringify({
resources: [] as any[] resources: [] as any[],
}) }),
}; };
} }
}); });

View File

@ -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);
}); });

View File

@ -45,8 +45,8 @@ function getDummyPod(opts: GetDummyPodOptions = getDummyPodDefaultOptions()): Po
uid: "1", uid: "1",
name: "test", name: "test",
resourceVersion: "v1", resourceVersion: "v1",
selfLink: "http" selfLink: "http",
} },
}); });
pod.spec = { pod.spec = {
@ -82,9 +82,9 @@ function getDummyPod(opts: GetDummyPodOptions = getDummyPodDefaultOptions()): Po
restartCount: i, restartCount: i,
state: { state: {
running: { running: {
startedAt: "before" startedAt: "before",
}, },
} },
}); });
} }
@ -107,9 +107,9 @@ function getDummyPod(opts: GetDummyPodOptions = getDummyPodDefaultOptions()): Po
startedAt: "before", startedAt: "before",
exitCode: i+1, exitCode: i+1,
finishedAt: "later", finishedAt: "later",
reason: `reason_${i}` reason: `reason_${i}`,
} },
} },
}); });
} }
@ -129,9 +129,9 @@ function getDummyPod(opts: GetDummyPodOptions = getDummyPodDefaultOptions()): Po
restartCount: i, restartCount: i,
state: { state: {
running: { running: {
startedAt: "before" startedAt: "before",
} },
} },
}); });
} }
@ -154,9 +154,9 @@ function getDummyPod(opts: GetDummyPodOptions = getDummyPodDefaultOptions()): Po
startedAt: "before", startedAt: "before",
exitCode: i+1, exitCode: i+1,
finishedAt: "later", finishedAt: "later",
reason: `reason_${i}` reason: `reason_${i}`,
} },
} },
}); });
} }
@ -183,7 +183,7 @@ describe("Pods", () => {
return { return {
image: "dummy", image: "dummy",
imagePullPolicy: "dummy", imagePullPolicy: "dummy",
name name,
}; };
} }
@ -231,7 +231,7 @@ describe("Pods", () => {
const pod = getDummyPod(); const pod = getDummyPod();
pod.spec.nodeSelector = { pod.spec.nodeSelector = {
"kubernetes.io/os": "foobar" "kubernetes.io/os": "foobar",
}; };
expect(pod.getSelectedNodeOs()).toStrictEqual("foobar"); expect(pod.getSelectedNodeOs()).toStrictEqual("foobar");
@ -241,7 +241,7 @@ describe("Pods", () => {
const pod = getDummyPod(); const pod = getDummyPod();
pod.spec.nodeSelector = { pod.spec.nodeSelector = {
"beta.kubernetes.io/os": "foobar1" "beta.kubernetes.io/os": "foobar1",
}; };
expect(pod.getSelectedNodeOs()).toStrictEqual("foobar1"); expect(pod.getSelectedNodeOs()).toStrictEqual("foobar1");
@ -252,7 +252,7 @@ describe("Pods", () => {
pod.spec.nodeSelector = { pod.spec.nodeSelector = {
"kubernetes.io/os": "foobar2", "kubernetes.io/os": "foobar2",
"beta.kubernetes.io/os": "foobar3" "beta.kubernetes.io/os": "foobar3",
}; };
expect(pod.getSelectedNodeOs()).toStrictEqual("foobar2"); expect(pod.getSelectedNodeOs()).toStrictEqual("foobar2");
@ -273,7 +273,7 @@ describe("Pods", () => {
type: "Ready", type: "Ready",
status: "foobar", status: "foobar",
lastProbeTime: 1, lastProbeTime: 1,
lastTransitionTime: "longer ago" lastTransitionTime: "longer ago",
}); });
expect(pod.hasIssues()).toStrictEqual(true); expect(pod.hasIssues()).toStrictEqual(true);
@ -286,7 +286,7 @@ describe("Pods", () => {
type: "dummy", type: "dummy",
status: "foobar", status: "foobar",
lastProbeTime: 1, lastProbeTime: 1,
lastTransitionTime: "longer ago" lastTransitionTime: "longer ago",
}); });
expect(pod.hasIssues()).toStrictEqual(false); expect(pod.hasIssues()).toStrictEqual(false);
@ -298,8 +298,8 @@ describe("Pods", () => {
pod.status.containerStatuses[0].state = { pod.status.containerStatuses[0].state = {
waiting: { waiting: {
reason: "CrashLookBackOff", reason: "CrashLookBackOff",
message: "too much foobar" message: "too much foobar",
} },
}; };
expect(pod.hasIssues()).toStrictEqual(true); expect(pod.hasIssues()).toStrictEqual(true);

View File

@ -41,19 +41,19 @@ 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: {
spec: { spec: {
replicas: 5 replicas: 5,
} },
} },
}, },
{ {
headers: { headers: {
"content-type": "application/merge-patch+json" "content-type": "application/merge-patch+json",
} },
}); });
}); });
}); });

View File

@ -98,7 +98,7 @@ export class ApiManager {
lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string { lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string {
const { const {
kind, apiVersion, name, kind, apiVersion, name,
namespace = parentObject.getNs() namespace = parentObject.getNs(),
} = ref; } = ref;
if (!kind) return ""; if (!kind) return "";

View File

@ -66,5 +66,5 @@ if (isClusterPageContext()) {
} }
export { export {
clusterRoleBindingApi clusterRoleBindingApi,
}; };

View File

@ -54,5 +54,5 @@ if (isClusterPageContext()) { // initialize automatically only when within a clu
} }
export { export {
clusterRoleApi clusterRoleApi,
}; };

View File

@ -49,7 +49,7 @@ export function getMetricsByNodeNames(nodeNames: string[], params?: IMetricsReqP
podCapacity: opts, podCapacity: opts,
podAllocatableCapacity: opts, podAllocatableCapacity: opts,
fsSize: opts, fsSize: opts,
fsUsage: opts fsUsage: opts,
}, params); }, params);
} }
@ -57,7 +57,7 @@ export enum ClusterStatus {
ACTIVE = "Active", ACTIVE = "Active",
CREATING = "Creating", CREATING = "Creating",
REMOVING = "Removing", REMOVING = "Removing",
ERROR = "Error" ERROR = "Error",
} }
export interface IClusterMetrics<T = IMetrics> { export interface IClusterMetrics<T = IMetrics> {
@ -135,5 +135,5 @@ if (isClusterPageContext()) { // initialize automatically only when within a clu
} }
export { export {
clusterApi clusterApi,
}; };

View File

@ -60,5 +60,5 @@ if (isClusterPageContext()) {
} }
export { export {
configMapApi configMapApi,
}; };

View File

@ -117,7 +117,7 @@ export class CustomResourceDefinition extends KubeObject {
params: { params: {
group: this.getGroup(), group: this.getGroup(),
name: this.getPluralName(), name: this.getPluralName(),
} },
}); });
} }
@ -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,
@ -217,7 +217,7 @@ export class CustomResourceDefinition extends KubeObject {
return { return {
...condition, ...condition,
isReady: status === "True", isReady: status === "True",
tooltip: `${message || reason} (${lastTransitionTime})` tooltip: `${message || reason} (${lastTransitionTime})`,
}; };
}); });
} }
@ -236,5 +236,5 @@ if (isClusterPageContext()) {
} }
export { export {
crdApi crdApi,
}; };

View File

@ -33,14 +33,14 @@ export class CronJobApi extends KubeApi<CronJob> {
return this.request.patch(this.getUrl(params), { return this.request.patch(this.getUrl(params), {
data: { data: {
spec: { spec: {
suspend: true suspend: true,
} },
} },
}, },
{ {
headers: { headers: {
"content-type": "application/strategic-merge-patch+json" "content-type": "application/strategic-merge-patch+json",
} },
}); });
} }
@ -48,14 +48,14 @@ export class CronJobApi extends KubeApi<CronJob> {
return this.request.patch(this.getUrl(params), { return this.request.patch(this.getUrl(params), {
data: { data: {
spec: { spec: {
suspend: false suspend: false,
} },
} },
}, },
{ {
headers: { headers: {
"content-type": "application/strategic-merge-patch+json" "content-type": "application/strategic-merge-patch+json",
} },
}); });
} }
} }
@ -153,5 +153,5 @@ if (isClusterPageContext()) {
} }
export { export {
cronJobApi cronJobApi,
}; };

View File

@ -129,5 +129,5 @@ if (isClusterPageContext()) {
} }
export { export {
daemonSetApi daemonSetApi,
}; };

View File

@ -44,14 +44,14 @@ export class DeploymentApi extends KubeApi<Deployment> {
return this.request.patch(this.getScaleApiUrl(params), { return this.request.patch(this.getScaleApiUrl(params), {
data: { data: {
spec: { spec: {
replicas replicas,
} },
} },
}, },
{ {
headers: { headers: {
"content-type": "application/merge-patch+json" "content-type": "application/merge-patch+json",
} },
}); });
} }
@ -61,16 +61,16 @@ 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() },
} },
} },
} },
} },
}, },
{ {
headers: { headers: {
"content-type": "application/strategic-merge-patch+json" "content-type": "application/strategic-merge-patch+json",
} },
}); });
} }
} }
@ -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;
@ -246,5 +246,5 @@ if (isClusterPageContext()) {
} }
export { export {
deploymentApi deploymentApi,
}; };

View File

@ -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;
} }
@ -159,5 +159,5 @@ if (isClusterPageContext()) {
} }
export { export {
endpointApi endpointApi,
}; };

View File

@ -87,5 +87,5 @@ if (isClusterPageContext()) {
} }
export { export {
eventApi eventApi,
}; };

View File

@ -191,7 +191,7 @@ const helmChartValidator = Joi.object<RawHelmChart>({
.items(Joi.string()) .items(Joi.string())
.options({ .options({
stripUnknown: { stripUnknown: {
arrays: true arrays: true,
}, },
}) })
.default(() => ([])), .default(() => ([])),
@ -200,7 +200,7 @@ const helmChartValidator = Joi.object<RawHelmChart>({
.items(Joi.string()) .items(Joi.string())
.options({ .options({
stripUnknown: { stripUnknown: {
arrays: true arrays: true,
}, },
}) })
.default(() => ([])), .default(() => ([])),
@ -209,7 +209,7 @@ const helmChartValidator = Joi.object<RawHelmChart>({
.items(Joi.string()) .items(Joi.string())
.options({ .options({
stripUnknown: { stripUnknown: {
arrays: true arrays: true,
}, },
}) })
.default(() => ([])), .default(() => ([])),
@ -218,7 +218,7 @@ const helmChartValidator = Joi.object<RawHelmChart>({
.items(helmChartMaintainerValidator) .items(helmChartMaintainerValidator)
.options({ .options({
stripUnknown: { stripUnknown: {
arrays: true arrays: true,
}, },
}) })
.default(() => ([])), .default(() => ([])),
@ -227,7 +227,7 @@ const helmChartValidator = Joi.object<RawHelmChart>({
.items(helmChartDependencyValidator) .items(helmChartDependencyValidator)
.options({ .options({
stripUnknown: { stripUnknown: {
arrays: true arrays: true,
}, },
}) })
.default(() => ([])), .default(() => ([])),

View File

@ -108,7 +108,7 @@ export async function getRelease(name: string, namespace: string): Promise<IRele
return { return {
...details, ...details,
resources resources,
}; };
} }
@ -122,7 +122,7 @@ export async function createRelease(payload: IReleaseCreatePayload): Promise<IRe
chart, chart,
values, values,
...data, ...data,
} },
}); });
} }
@ -136,7 +136,7 @@ export async function updateRelease(name: string, namespace: string, payload: IR
chart, chart,
values, values,
...data, ...data,
} },
}); });
} }

View File

@ -111,7 +111,7 @@ export class HorizontalPodAutoscaler extends KubeObject {
return { return {
...condition, ...condition,
isReady: status === "True", isReady: status === "True",
tooltip: `${message || reason} (${lastTransitionTime})` tooltip: `${message || reason} (${lastTransitionTime})`,
}; };
}); });
} }
@ -143,7 +143,7 @@ export class HorizontalPodAutoscaler extends KubeObject {
getMetricValues(metric: IHpaMetric): string { getMetricValues(metric: IHpaMetric): string {
const metricType = metric.type.toLowerCase(); const metricType = metric.type.toLowerCase();
const currentMetric = this.getCurrentMetrics().find(current => const currentMetric = this.getCurrentMetrics().find(current =>
metric.type == current.type && this.getMetricName(metric) == this.getMetricName(current) metric.type == current.type && this.getMetricName(metric) == this.getMetricName(current),
); );
const current = currentMetric ? currentMetric[metricType] : null; const current = currentMetric ? currentMetric[metricType] : null;
const target = metric[metricType]; const target = metric[metricType];
@ -173,5 +173,5 @@ if (isClusterPageContext()) {
} }
export { export {
hpaApi hpaApi,
}; };

View File

@ -30,13 +30,13 @@ export class IngressApi extends KubeApi<Ingress> {
} }
export function getMetricsForIngress(ingress: string, namespace: string): Promise<IIngressMetrics> { export function getMetricsForIngress(ingress: string, namespace: string): Promise<IIngressMetrics> {
const opts = { category: "ingress", ingress }; const opts = { category: "ingress", ingress, namespace };
return metricsApi.getMetrics({ return metricsApi.getMetrics({
bytesSentSuccess: opts, bytesSentSuccess: opts,
bytesSentFailure: opts, bytesSentFailure: opts,
requestDurationSeconds: opts, requestDurationSeconds: opts,
responseDurationSeconds: opts responseDurationSeconds: opts,
}, { }, {
namespace, namespace,
}); });
@ -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 [];
@ -160,12 +160,12 @@ export class Ingress extends KubeObject {
return { return {
serviceName, serviceName,
servicePort servicePort,
}; };
} }
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
@ -216,5 +216,5 @@ if (isClusterPageContext()) {
} }
export { export {
ingressApi ingressApi,
}; };

View File

@ -124,7 +124,7 @@ export class Job extends WorkloadKubeObject {
delete() { delete() {
const params: JsonApiParams = { const params: JsonApiParams = {
query: { propagationPolicy: "Background" } query: { propagationPolicy: "Background" },
}; };
return super.delete(params); return super.delete(params);
@ -158,5 +158,5 @@ if (isClusterPageContext()) {
} }
export { export {
jobApi jobApi,
}; };

View File

@ -90,5 +90,5 @@ if (isClusterPageContext()) {
} }
export { export {
limitRangeApi limitRangeApi,
}; };

View File

@ -87,13 +87,13 @@ export const metricsApi = {
query: { query: {
start, end, step, start, end, step,
"kubernetes_namespace": namespace, "kubernetes_namespace": namespace,
} },
}); });
}, },
async getMetricProviders(): Promise<MetricProviderInfo[]> { async getMetricProviders(): Promise<MetricProviderInfo[]> {
return apiBase.get("/metrics/providers"); return apiBase.get("/metrics/providers");
} },
}; };
export function normalizeMetrics(metrics: IMetrics, frames = 60): IMetrics { export function normalizeMetrics(metrics: IMetrics, frames = 60): IMetrics {
@ -103,7 +103,7 @@ export function normalizeMetrics(metrics: IMetrics, frames = 60): IMetrics {
resultType: "", resultType: "",
result: [{ result: [{
metric: {}, metric: {},
values: [] values: [],
} as IMetricsResult], } as IMetricsResult],
}, },
status: "", status: "",
@ -144,7 +144,7 @@ export function normalizeMetrics(metrics: IMetrics, frames = 60): IMetrics {
// always return at least empty values array // always return at least empty values array
result.push({ result.push({
metric: {}, metric: {},
values: [] values: [],
} as IMetricsResult); } as IMetricsResult);
} }

View File

@ -79,5 +79,5 @@ if (isClusterPageContext()) {
} }
export { export {
namespacesApi namespacesApi,
}; };

View File

@ -106,5 +106,5 @@ if (isClusterPageContext()) {
} }
export { export {
networkPolicyApi networkPolicyApi,
}; };

View File

@ -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,
@ -40,7 +40,7 @@ export function getMetricsForAllNodes(): Promise<INodeMetrics> {
cpuUsage: opts, cpuUsage: opts,
cpuCapacity: opts, cpuCapacity: opts,
fsSize: opts, fsSize: opts,
fsUsage: opts fsUsage: opts,
}); });
} }
@ -259,5 +259,5 @@ if (isClusterPageContext()) {
} }
export { export {
nodesApi nodesApi,
}; };

View File

@ -35,9 +35,9 @@ export function getMetricsForPvc(pvc: PersistentVolumeClaim): Promise<IPvcMetric
return metricsApi.getMetrics({ return metricsApi.getMetrics({
diskUsage: opts, diskUsage: opts,
diskCapacity: opts diskCapacity: opts,
}, { }, {
namespace: opts.namespace namespace: opts.namespace,
}); });
} }
@ -88,7 +88,7 @@ export class PersistentVolumeClaim extends KubeObject {
return pods.filter(pod => { return pods.filter(pod => {
return pod.getVolumes().filter(volume => return pod.getVolumes().filter(volume =>
volume.persistentVolumeClaim && volume.persistentVolumeClaim &&
volume.persistentVolumeClaim.claimName === this.getName() volume.persistentVolumeClaim.claimName === this.getName(),
).length > 0; ).length > 0;
}); });
} }
@ -128,5 +128,5 @@ if (isClusterPageContext()) {
} }
export { export {
pvcApi pvcApi,
}; };

View File

@ -111,5 +111,5 @@ if (isClusterPageContext()) {
} }
export { export {
persistentVolumeApi persistentVolumeApi,
}; };

View File

@ -50,5 +50,5 @@ if (isClusterPageContext()) {
} }
export { export {
podMetricsApi podMetricsApi,
}; };

View File

@ -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
@ -82,5 +82,5 @@ if (isClusterPageContext()) {
} }
export { export {
pdbApi pdbApi,
}; };

View File

@ -82,7 +82,7 @@ export enum PodStatus {
PENDING = "Pending", PENDING = "Pending",
RUNNING = "Running", RUNNING = "Running",
SUCCEEDED = "Succeeded", SUCCEEDED = "Succeeded",
EVICTED = "Evicted" EVICTED = "Evicted",
} }
export interface IPodContainer extends Partial<Record<PodContainerProbe, IContainerProbe>> { export interface IPodContainer extends Partial<Record<PodContainerProbe, IContainerProbe>> {
@ -310,7 +310,7 @@ export class Pod extends WorkloadKubeObject {
const runningContainerNames = new Set( const runningContainerNames = new Set(
this.getContainerStatuses() this.getContainerStatuses()
.filter(({ state }) => state.running) .filter(({ state }) => state.running)
.map(({ name }) => name) .map(({ name }) => name),
); );
return this.getAllContainers() return this.getAllContainers()
@ -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(": "));
} }
@ -466,7 +466,7 @@ export class Pod extends WorkloadKubeObject {
timeoutSeconds = 0, timeoutSeconds = 0,
periodSeconds = 0, periodSeconds = 0,
successThreshold = 0, successThreshold = 0,
failureThreshold = 0 failureThreshold = 0,
} = probeData; } = probeData;
// HTTP Request // HTTP Request
@ -529,5 +529,5 @@ if (isClusterPageContext()) {
} }
export { export {
podsApi podsApi,
}; };

View File

@ -127,5 +127,5 @@ if (isClusterPageContext()) {
} }
export { export {
pspApi pspApi,
}; };

View File

@ -44,9 +44,9 @@ export class ReplicaSetApi extends KubeApi<ReplicaSet> {
data: { data: {
metadata: params, metadata: params,
spec: { spec: {
replicas replicas,
} },
} },
}); });
} }
} }
@ -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: {
@ -133,5 +133,5 @@ if (isClusterPageContext()) {
} }
export { export {
replicaSetApi replicaSetApi,
}; };

View File

@ -25,7 +25,7 @@ import { apiBase } from "../index";
import type { Patch } from "rfc6902"; import type { Patch } from "rfc6902";
export const annotations = [ export const annotations = [
"kubectl.kubernetes.io/last-applied-configuration" "kubectl.kubernetes.io/last-applied-configuration",
]; ];
export async function update(resource: object | string): Promise<KubeJsonApiData> { export async function update(resource: object | string): Promise<KubeJsonApiData> {

View File

@ -90,5 +90,5 @@ if (isClusterPageContext()) {
} }
export { export {
resourceQuotaApi resourceQuotaApi,
}; };

View File

@ -71,5 +71,5 @@ if (isClusterPageContext()) {
} }
export { export {
roleBindingApi roleBindingApi,
}; };

View File

@ -51,5 +51,5 @@ if (isClusterPageContext()) {
} }
export{ export{
roleApi roleApi,
}; };

View File

@ -79,5 +79,5 @@ if (isClusterPageContext()) {
} }
export { export {
secretsApi secretsApi,
}; };

View File

@ -27,7 +27,7 @@ export class SelfSubjectRulesReviewApi extends KubeApi<SelfSubjectRulesReview> {
create({ namespace = "default" }): Promise<SelfSubjectRulesReview> { create({ namespace = "default" }): Promise<SelfSubjectRulesReview> {
return super.create({}, { return super.create({}, {
spec: { spec: {
namespace namespace,
}, },
}); });
} }
@ -82,7 +82,7 @@ export class SelfSubjectRulesReview extends KubeObject {
const separator = apiGroup == "" ? "" : "."; const separator = apiGroup == "" ? "" : ".";
return resource + separator + apiGroup; return resource + separator + apiGroup;
}) }),
}; };
} }
} }
@ -96,6 +96,6 @@ if (isClusterPageContext()) {
} }
export { export {
selfSubjectRulesReviewApi selfSubjectRulesReviewApi,
}; };

View File

@ -62,5 +62,5 @@ if (isClusterPageContext()) {
} }
export { export {
serviceAccountsApi serviceAccountsApi,
}; };

View File

@ -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() {
@ -153,5 +157,5 @@ if (isClusterPageContext()) {
} }
export { export {
serviceApi serviceApi,
}; };

View File

@ -42,14 +42,14 @@ export class StatefulSetApi extends KubeApi<StatefulSet> {
return this.request.patch(this.getScaleApiUrl(params), { return this.request.patch(this.getScaleApiUrl(params), {
data: { data: {
spec: { spec: {
replicas replicas,
} },
} },
}, },
{ {
headers: { headers: {
"content-type": "application/merge-patch+json" "content-type": "application/merge-patch+json",
} },
}); });
} }
} }
@ -162,5 +162,5 @@ if (isClusterPageContext()) {
} }
export { export {
statefulSetApi statefulSetApi,
}; };

View File

@ -72,5 +72,5 @@ if (isClusterPageContext()) {
} }
export { export {
storageClassApi storageClassApi,
}; };

View File

@ -42,8 +42,8 @@ if (typeof window === "undefined") {
debug: isDevelopment || isDebugging, debug: isDevelopment || isDebugging,
}, { }, {
headers: { headers: {
"Host": `localhost:${params.port}` "Host": `localhost:${params.port}`,
} },
}); });
}); });
} else { } else {
@ -53,8 +53,8 @@ if (typeof window === "undefined") {
debug: isDevelopment || isDebugging, debug: isDevelopment || isDebugging,
}, { }, {
headers: { headers: {
"Host": window.location.host "Host": window.location.host,
} },
}); });
} }
@ -62,15 +62,15 @@ if (isClusterPageContext()) {
apiKube = new KubeJsonApi({ apiKube = new KubeJsonApi({
serverAddress: `http://127.0.0.1:${window.location.port}`, serverAddress: `http://127.0.0.1:${window.location.port}`,
apiBase: apiKubePrefix, apiBase: apiKubePrefix,
debug: isDevelopment debug: isDevelopment,
}, { }, {
headers: { headers: {
"Host": window.location.host "Host": window.location.host,
} },
}); });
} }
export { export {
apiBase, apiBase,
apiKube apiKube,
}; };

View File

@ -57,12 +57,12 @@ export interface JsonApiConfig {
export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> { export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
static reqInitDefault: RequestInit = { static reqInitDefault: RequestInit = {
headers: { headers: {
"content-type": "application/json" "content-type": "application/json",
} },
}; };
static configDefault: Partial<JsonApiConfig> = { static configDefault: Partial<JsonApiConfig> = {
debug: false debug: false,
}; };
constructor(public readonly config: JsonApiConfig, protected reqInit?: RequestInit) { constructor(public readonly config: JsonApiConfig, protected reqInit?: RequestInit) {
@ -87,7 +87,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
{}, {},
this.reqInit, this.reqInit,
await this.getRequestOptions(), await this.getRequestOptions(),
init init,
); );
const { query } = params || {} as P; const { query } = params || {} as P;
@ -126,7 +126,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
{}, {},
this.reqInit, this.reqInit,
await this.getRequestOptions(), await this.getRequestOptions(),
init init,
); );
const { data, query } = params || {} as P; const { data, query } = params || {} as P;
@ -201,7 +201,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
protected writeLog(log: JsonApiLog) { protected writeLog(log: JsonApiLog) {
const { method, reqUrl, ...params } = log; const { method, reqUrl, ...params } = log;
logger.info(`[JSON-API] request ${method} ${reqUrl}`, params); logger.debug(`[JSON-API] request ${method} ${reqUrl}`, params);
} }
} }

View File

@ -123,13 +123,13 @@ export function forCluster<T extends KubeObject>(cluster: ILocalKubeApiConfig, k
debug: isDevelopment, debug: isDevelopment,
}, { }, {
headers: { headers: {
"Host": `${cluster.metadata.uid}.localhost:${url.port}` "Host": `${cluster.metadata.uid}.localhost:${url.port}`,
} },
}); });
return new KubeApi({ return new KubeApi({
objectConstructor: kubeClass, objectConstructor: kubeClass,
request request,
}); });
} }
@ -166,15 +166,15 @@ export function forRemoteCluster<T extends KubeObject>(config: IRemoteKubeApiCon
...(token ? { ...(token ? {
getRequestOptions: async () => ({ getRequestOptions: async () => ({
headers: { headers: {
"Authorization": `Bearer ${isFunction(token) ? await token() : token}` "Authorization": `Bearer ${isFunction(token) ? await token() : token}`,
} },
}) }),
} : {}) } : {}),
}, reqInit); }, reqInit);
return new KubeApi({ return new KubeApi({
objectConstructor: kubeClass, objectConstructor: kubeClass,
request request,
}); });
} }
@ -221,7 +221,7 @@ export class KubeApi<T extends KubeObject> {
objectConstructor, objectConstructor,
request = apiKube, request = apiKube,
kind = options.objectConstructor?.kind, kind = options.objectConstructor?.kind,
isNamespaced = options.objectConstructor?.namespaced isNamespaced = options.objectConstructor?.namespaced,
} = options || {}; } = options || {};
if (!options.apiBase) { if (!options.apiBase) {
@ -292,7 +292,7 @@ export class KubeApi<T extends KubeObject> {
return { return {
apiPrefix: this.apiPrefix, apiPrefix: this.apiPrefix,
apiGroup: this.apiGroup apiGroup: this.apiGroup,
}; };
} }
@ -306,10 +306,10 @@ export class KubeApi<T extends KubeObject> {
// The apiPrefix and apiGroup might change due to fallbackApiBases, so we must override them // The apiPrefix and apiGroup might change due to fallbackApiBases, so we must override them
Object.defineProperty(this, "apiPrefix", { Object.defineProperty(this, "apiPrefix", {
value: apiPrefix value: apiPrefix,
}); });
Object.defineProperty(this, "apiGroup", { Object.defineProperty(this, "apiGroup", {
value: apiGroup value: apiGroup,
}); });
const res = await this.request.get<IKubePreferredVersion>(`${this.apiPrefix}/${this.apiGroup}`); const res = await this.request.get<IKubePreferredVersion>(`${this.apiPrefix}/${this.apiGroup}`);
@ -444,9 +444,9 @@ export class KubeApi<T extends KubeObject> {
apiVersion: this.apiVersionWithGroup, apiVersion: this.apiVersionWithGroup,
metadata: { metadata: {
name, name,
namespace namespace,
} },
}, data) }, data),
}); });
const parsed = this.parseResponse(res); const parsed = this.parseResponse(res);

View File

@ -317,7 +317,7 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
protected bindWatchEventsUpdater(delay = 1000) { protected bindWatchEventsUpdater(delay = 1000) {
reaction(() => this.eventsBuffer.length, this.updateFromEventsBuffer, { reaction(() => this.eventsBuffer.length, this.updateFromEventsBuffer, {
delay delay,
}); });
} }
@ -352,7 +352,7 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
const watch = () => this.api.watch({ const watch = () => this.api.watch({
namespace, namespace,
abortController, abortController,
callback callback,
}); });
const { signal } = abortController; const { signal } = abortController;
@ -375,8 +375,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

View File

@ -82,7 +82,7 @@ export class KubeWatchApi {
} }
subscribeStores(stores: KubeObjectStore<KubeObject>[], opts: IKubeWatchSubscribeStoreOptions = {}): Disposer { subscribeStores(stores: KubeObjectStore<KubeObject>[], opts: IKubeWatchSubscribeStoreOptions = {}): Disposer {
const { preload = true, waitUntilLoaded = true, loadOnce = false, } = opts; const { preload = true, waitUntilLoaded = true, loadOnce = false } = opts;
const subscribingNamespaces = opts.namespaces ?? this.context?.allNamespaces ?? []; const subscribingNamespaces = opts.namespaces ?? this.context?.allNamespaces ?? [];
const unsubscribeList: Function[] = []; const unsubscribeList: Function[] = [];
let isUnsubscribed = false; let isUnsubscribed = false;
@ -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;
} }

View File

@ -121,7 +121,7 @@ function loadToOptions(rawYaml: string): OptionsResult {
allowUnknown: true, allowUnknown: true,
stripUnknown: { stripUnknown: {
arrays: true, arrays: true,
} },
}); });
const { const {
clusters: rawClusters, clusters: rawClusters,
@ -210,16 +210,16 @@ export function dumpConfigYaml(kubeConfig: Partial<KubeConfig>): string {
"certificate-authority-data": cluster.caData, "certificate-authority-data": cluster.caData,
"certificate-authority": cluster.caFile, "certificate-authority": cluster.caFile,
server: cluster.server, server: cluster.server,
"insecure-skip-tls-verify": cluster.skipTLSVerify "insecure-skip-tls-verify": cluster.skipTLSVerify,
} },
})); }));
const contexts = kubeConfig.contexts.map(context => ({ const contexts = kubeConfig.contexts.map(context => ({
name: context.name, name: context.name,
context: { context: {
cluster: context.cluster, cluster: context.cluster,
user: context.user, user: context.user,
namespace: context.namespace namespace: context.namespace,
} },
})); }));
const users = kubeConfig.users.map(user => ({ const users = kubeConfig.users.map(user => ({
name: user.name, name: user.name,
@ -232,8 +232,8 @@ export function dumpConfigYaml(kubeConfig: Partial<KubeConfig>): string {
exec: user.exec, exec: user.exec,
token: user.token, token: user.token,
username: user.username, username: user.username,
password: user.password password: user.password,
} },
})); }));
const config = { const config = {
apiVersion: "v1", apiVersion: "v1",

View File

@ -56,7 +56,7 @@ if (ipcMain) {
}, },
}), }),
), ),
}) }),
); );
if (!isTestEnv) { if (!isTestEnv) {
@ -73,7 +73,7 @@ if (ipcMain) {
maxsize: 16 * 1024, maxsize: 16 * 1024,
maxFiles: 16, maxFiles: 16,
tailable: true, tailable: true,
}) }),
); );
} }
} else { } else {

View File

@ -23,7 +23,7 @@ import type { RouteProps } from "react-router";
import { buildURL } from "../utils/buildUrl"; import { buildURL } from "../utils/buildUrl";
export const addClusterRoute: RouteProps = { export const addClusterRoute: RouteProps = {
path: "/add-cluster" path: "/add-cluster",
}; };
export const addClusterURL = buildURL(addClusterRoute.path); export const addClusterURL = buildURL(addClusterRoute.path);

View File

@ -27,7 +27,7 @@ export interface CatalogViewRouteParam {
kind?: string; kind?: string;
} }
export const catalogRoute: RouteProps = { export const catalogRoute: RouteProps = {
path: "/catalog/:group?/:kind?" path: "/catalog/:group?/:kind?",
}; };
export const getPreviousTabUrl = (path: string) => { export const getPreviousTabUrl = (path: string) => {
@ -36,8 +36,8 @@ export const getPreviousTabUrl = (path: string) => {
return catalogURL({ return catalogURL({
params: { params: {
group: group || browseCatalogTab, group: group || browseCatalogTab,
kind kind,
} },
}); });
}; };

View File

@ -23,7 +23,7 @@ import type { RouteProps } from "react-router";
import { buildURL } from "../utils/buildUrl"; import { buildURL } from "../utils/buildUrl";
export const clusterRoute: RouteProps = { export const clusterRoute: RouteProps = {
path: "/overview" path: "/overview",
}; };
export const clusterURL = buildURL(clusterRoute.path); export const clusterURL = buildURL(clusterRoute.path);

Some files were not shown because too many files have changed in this diff Show More