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: {
react: {
version: packageJson.devDependencies.react || "detect",
}
},
},
overrides: [
{
files: [
"**/*.js"
"**/*.js",
],
extends: [
"eslint:recommended",
],
env: {
node: true
node: true,
},
parserOptions: {
ecmaVersion: 2018,
@ -51,32 +51,44 @@ module.exports = {
plugins: [
"header",
"unused-imports",
"react-hooks"
"react-hooks",
],
rules: {
"header/header": [2, "./license-header"],
"comma-dangle": ["error", "always-multiline"],
"comma-spacing": "error",
"indent": ["error", 2, {
"SwitchCase": 1,
}],
"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-vars": [
"warn", {
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true,
}
},
],
"quotes": ["error", "double", {
"avoidEscape": true,
"allowTemplateLiterals": true,
}],
"object-curly-spacing": ["error", "always", {
"objectsInObjects": false,
"arraysInObjects": true,
}],
"linebreak-style": ["error", "unix"],
"eol-last": ["error", "always"],
"semi": ["error", "always"],
"object-shorthand": "error",
"prefer-template": "error",
"template-curly-spacing": "error",
"no-unused-expressions": "error",
"padding-line-between-statements": [
"error",
{ "blankLine": "always", "prev": "*", "next": "return" },
@ -84,9 +96,10 @@ module.exports = {
{ "blankLine": "always", "prev": "*", "next": "function" },
{ "blankLine": "always", "prev": "*", "next": "class" },
{ "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: [
@ -98,7 +111,7 @@ module.exports = {
],
plugins: [
"header",
"unused-imports"
"unused-imports",
],
parserOptions: {
ecmaVersion: 2018,
@ -115,14 +128,24 @@ module.exports = {
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-interface": "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-vars-ts": [
"warn", {
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true,
}
},
],
"comman-dangle": "off",
"@typescript-eslint/comma-dangle": ["error", "always-multiline"],
"comma-spacing": "off",
"@typescript-eslint/comma-spacing": "error",
"indent": ["error", 2, {
"SwitchCase": 1,
}],
@ -130,6 +153,11 @@ module.exports = {
"avoidEscape": true,
"allowTemplateLiterals": true,
}],
"object-curly-spacing": "off",
"@typescript-eslint/object-curly-spacing": ["error", "always", {
"objectsInObjects": false,
"arraysInObjects": true,
}],
"react/prop-types": "off",
"semi": "off",
"@typescript-eslint/semi": ["error"],
@ -138,6 +166,8 @@ module.exports = {
"object-shorthand": "error",
"prefer-template": "error",
"template-curly-spacing": "error",
"no-unused-expressions": "off",
"@typescript-eslint/no-unused-expressions": "error",
"padding-line-between-statements": [
"error",
{ "blankLine": "always", "prev": "*", "next": "return" },
@ -145,8 +175,9 @@ module.exports = {
{ "blankLine": "always", "prev": "*", "next": "function" },
{ "blankLine": "always", "prev": "*", "next": "class" },
{ "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",
plugins: [
"header",
"unused-imports"
"unused-imports",
],
extends: [
"plugin:@typescript-eslint/recommended",
@ -183,14 +214,24 @@ module.exports = {
"@typescript-eslint/no-empty-function": "off",
"react/display-name": "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-vars-ts": [
"warn", {
"vars": "all",
"args": "after-used",
"ignoreRestSiblings": true,
}
},
],
"comman-dangle": "off",
"@typescript-eslint/comma-dangle": ["error", "always-multiline"],
"comma-spacing": "off",
"@typescript-eslint/comma-spacing": "error",
"indent": ["error", 2, {
"SwitchCase": 1,
}],
@ -198,6 +239,11 @@ module.exports = {
"avoidEscape": true,
"allowTemplateLiterals": true,
}],
"object-curly-spacing": "off",
"@typescript-eslint/object-curly-spacing": ["error", "always", {
"objectsInObjects": false,
"arraysInObjects": true,
}],
"react/prop-types": "off",
"semi": "off",
"@typescript-eslint/semi": ["error"],
@ -206,6 +252,8 @@ module.exports = {
"object-shorthand": "error",
"prefer-template": "error",
"template-curly-spacing": "error",
"no-unused-expressions": "off",
"@typescript-eslint/no-unused-expressions": "error",
"padding-line-between-statements": [
"error",
{ "blankLine": "always", "prev": "*", "next": "return" },
@ -213,11 +261,12 @@ module.exports = {
{ "blankLine": "always", "prev": "*", "next": "function" },
{ "blankLine": "always", "prev": "*", "next": "class" },
{ "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/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"
target "13.6.0"
target "13.6.1"
runtime "electron"

View File

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

View File

@ -10,9 +10,9 @@ Lens releases are built by CICD automatically on git tags. The typical release p
- `major`
- `minor`
- `patch`
- `premajor` [--preid=<prerelease-id>]
- `preminor` [--preid=<prerelease-id>]
- `prepatch` [--preid=<prerelease-id>]
- `premajor [--preid=<prerelease-id>]`
- `preminor [--preid=<prerelease-id>]`
- `prepatch [--preid=<prerelease-id>]`
- `prerelease [--preid=<prerelease-id>]`
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 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. 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

View File

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

View File

@ -28,7 +28,7 @@ const helmVersion = packageInfo.config.bundledHelmVersion;
if (!isWindows) {
Promise.all([
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 {
new HelmCli(path.join(process.cwd(), "binaries", "client", "x64"), helmVersion).ensureBinary();

View File

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

View File

@ -27,37 +27,37 @@ export default class EventResourceStatusRendererExtension extends Renderer.LensE
{
kind: "Pod",
apiVersions: ["v1"],
resolve: (pod: Renderer.K8sApi.Pod) => resolveStatusForPods(pod)
resolve: (pod: Renderer.K8sApi.Pod) => resolveStatusForPods(pod),
},
{
kind: "ReplicaSet",
apiVersions: ["v1"],
resolve: (replicaSet: Renderer.K8sApi.ReplicaSet) => resolveStatus(replicaSet)
resolve: (replicaSet: Renderer.K8sApi.ReplicaSet) => resolveStatus(replicaSet),
},
{
kind: "Deployment",
apiVersions: ["apps/v1"],
resolve: (deployment: Renderer.K8sApi.Deployment) => resolveStatus(deployment)
resolve: (deployment: Renderer.K8sApi.Deployment) => resolveStatus(deployment),
},
{
kind: "StatefulSet",
apiVersions: ["apps/v1"],
resolve: (statefulSet: Renderer.K8sApi.StatefulSet) => resolveStatus(statefulSet)
resolve: (statefulSet: Renderer.K8sApi.StatefulSet) => resolveStatus(statefulSet),
},
{
kind: "DaemonSet",
apiVersions: ["apps/v1"],
resolve: (daemonSet: Renderer.K8sApi.DaemonSet) => resolveStatus(daemonSet)
resolve: (daemonSet: Renderer.K8sApi.DaemonSet) => resolveStatus(daemonSet),
},
{
kind: "Job",
apiVersions: ["batch/v1"],
resolve: (job: Renderer.K8sApi.Job) => resolveStatus(job)
resolve: (job: Renderer.K8sApi.Job) => resolveStatus(job),
},
{
kind: "CronJob",
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 {
level: KubeObjectStatusLevel.WARNING,
text: `${event.message}`,
timestamp: event.metadata.creationTimestamp
timestamp: event.metadata.creationTimestamp,
};
}
@ -62,7 +62,7 @@ export function resolveStatusForPods(pod: Pod): KubeObjectStatus {
return {
level: KubeObjectStatusLevel.WARNING,
text: `${event.message}`,
timestamp: event.metadata.creationTimestamp
timestamp: event.metadata.creationTimestamp,
};
}
@ -83,6 +83,6 @@ export function resolveStatusForCronJobs(cronJob: CronJob): KubeObjectStatus {
return {
level: KubeObjectStatusLevel.WARNING,
text: `${event.message}`,
timestamp: event.metadata.creationTimestamp
timestamp: event.metadata.creationTimestamp,
};
}

View File

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

View File

@ -31,12 +31,12 @@ export default class ClusterMetricsFeatureExtension extends Renderer.LensExtensi
title: "Lens Metrics",
priority: 5,
components: {
View: ({ entity = null }: { entity: Common.Catalog.KubernetesCluster}) => {
View: ({ entity = null }: { entity: Common.Catalog.KubernetesCluster }) => {
return (
<MetricsSettings cluster={entity} />
);
}
}
}
},
},
},
];
}

View File

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

View File

@ -92,11 +92,11 @@ export class MetricsFeature {
}
async getStatus(): Promise<MetricsStatus> {
const status: MetricsStatus = { installed: false, canUpgrade: false};
const status: MetricsStatus = { installed: false, canUpgrade: false };
try {
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) {
const currentVersion = namespace.metadata.annotations?.extensionVersion || "0.0.0";

View File

@ -30,7 +30,7 @@ const {
},
Component: {
SubTitle, FormSwitch, Switcher, Button,
}
},
} = Renderer;
interface Props {
@ -47,7 +47,7 @@ export class MetricsSettings extends React.Component<Props> {
@observable featureStates = {
prometheus: false,
kubeStateMetrics: false,
nodeExporter: false
nodeExporter: false,
};
@observable canUpgrade = false;
@observable upgrading = false;
@ -56,7 +56,7 @@ export class MetricsSettings extends React.Component<Props> {
config: MetricsConfiguration = {
prometheus: {
enabled: false
enabled: false,
},
persistence: {
enabled: false,
@ -114,7 +114,7 @@ export class MetricsSettings extends React.Component<Props> {
const statefulSet = forCluster(this.props.cluster, StatefulSet);
try {
await statefulSet.get({name: "prometheus", namespace: "lens-metrics"});
await statefulSet.get({ name: "prometheus", namespace: "lens-metrics" });
this.featureStates.prometheus = true;
} catch(e) {
if (e?.error?.code === 404) {
@ -127,7 +127,7 @@ export class MetricsSettings extends React.Component<Props> {
const deployment = forCluster(this.props.cluster, Deployment);
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;
} catch(e) {
if (e?.error?.code === 404) {
@ -140,7 +140,7 @@ export class MetricsSettings extends React.Component<Props> {
const daemonSet = forCluster(this.props.cluster, DaemonSet);
try {
await daemonSet.get({name: "node-exporter", namespace: "lens-metrics"});
await daemonSet.get({ name: "node-exporter", namespace: "lens-metrics" });
this.featureStates.nodeExporter = true;
} catch(e) {
if (e?.error?.code === 404) {
@ -207,14 +207,14 @@ export class MetricsSettings extends React.Component<Props> {
<>
{ this.props.cluster.status.phase !== "connected" && (
<section>
<p style={ {color: "var(--colorError)"} }>
<p style={ { color: "var(--colorError)" } }>
Lens Metrics settings requires established connection to the cluster.
</p>
</section>
)}
{ !this.isActiveMetricsProvider && (
<section>
<p style={ {color: "var(--colorError)"} }>
<p style={ { color: "var(--colorError)" } }>
Other metrics provider is currently active. See &quot;Metrics&quot; tab for details.
</p>
</section>

View File

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

View File

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

View File

@ -20,7 +20,7 @@
*/
import React from "react";
import { Renderer } from "@k8slens/extensions";
import { Common, Renderer } from "@k8slens/extensions";
type Node = Renderer.K8sApi.Node;
@ -32,8 +32,11 @@ const {
MenuItem,
Icon,
},
Navigation
Navigation,
} = Renderer;
const {
App,
} = Common;
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) {
const { object: node, toolbar } = props;
if (!node) return null;
if (!node) {
return null;
}
const nodeName = node.getName();
const kubectlPath = App.Preferences.getKubectlPath() || "kubectl";
const sendToTerminal = (command: string) => {
terminalStore.sendCommand(command, {
@ -62,15 +69,15 @@ export function NodeMenu(props: NodeMenuProps) {
};
const cordon = () => {
sendToTerminal(`kubectl cordon ${nodeName}`);
sendToTerminal(`${kubectlPath} cordon ${nodeName}`);
};
const unCordon = () => {
sendToTerminal(`kubectl uncordon ${nodeName}`);
sendToTerminal(`${kubectlPath} uncordon ${nodeName}`);
};
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({
ok: () => sendToTerminal(command),

View File

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

View File

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

View File

@ -39,6 +39,7 @@ const {
} = Renderer;
const {
Util,
App,
} = Common;
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> {
async attachToPod(container?: string) {
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") {
command = `exec ${command}`;
commandParts.unshift("exec");
}
if (container) {
commandParts.push("-c", container);
}
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,
tabId: shell.id
tabId: shell.id,
});
Navigation.hideDetails();
}

View File

@ -39,6 +39,7 @@ const {
} = Renderer;
const {
Util,
App,
} = Common;
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> {
async execShell(container?: string) {
Navigation.hideDetails();
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") {
command = `exec ${command}`;
commandParts.unshift("exec");
}
if (container) {
commandParts.push("-c", container);
}
commandParts.push("--");
if (pod.getSelectedNodeOs() === "windows") {
command = `${command} powershell`;
commandParts.push("powershell");
} else {
command = `${command} sh -c "clear; (bash || ash || sh)"`;
commandParts.push('sh -c "clear; (bash || ash || sh)"');
}
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,
tabId: shell.id
tabId: shell.id,
});
Navigation.hideDetails();
}
render() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,7 +34,7 @@ describe("event bus tests", () => {
event = data;
});
appEventBus.emit({name: "foo", action: "bar"});
appEventBus.emit({ name: "foo", action: "bar" });
expect(event.name).toBe("foo");
});
});

View File

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

View File

@ -100,7 +100,7 @@ describe("kube helpers", () => {
describe("with invalid context object", () => {
it("returns an error", () => {
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", () => {
it("returns an error", () => {
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", () => {
it("returns an error", () => {
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 () => {
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));
expect(config.getCurrentContext()).toBe("minikube");
@ -209,7 +209,7 @@ describe("kube helpers", () => {
});
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);
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
@ -218,7 +218,7 @@ describe("kube helpers", () => {
});
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);
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
@ -227,7 +227,7 @@ describe("kube helpers", () => {
});
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);
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));
@ -236,8 +236,8 @@ describe("kube helpers", () => {
});
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-3", user: "cluster-3"}, name: "cluster-3"});
mockKubeConfig.contexts.push({ context: { cluster: "cluster-2", user: "" }, name: "cluster-2" });
mockKubeConfig.contexts.push({ context: { cluster: "cluster-3", user: "cluster-3" }, name: "cluster-3" });
expect(mockKubeConfig.contexts.length).toBe(3);
const { config } = loadConfigFromString(JSON.stringify(mockKubeConfig));

View File

@ -37,7 +37,7 @@ let searchStore: SearchStore = null;
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.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", () => {

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,27 +23,25 @@ import esbuild from "esbuild";
/**
* 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
*
* @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
*/
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 {
test: testRegExp,
loader: "esbuild-loader",
options: {
loader: "tsx",
target: "es2015",
implementation: esbuild
implementation: esbuild,
},
};
}
@ -55,8 +53,8 @@ const getTSLoader = (
loader: "ts-loader",
options: {
transpileOnly,
}
}
},
},
};
};

View File

@ -73,8 +73,8 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
protected fromStore(data: Partial<HotbarStoreModel> = {}) {
if (!data.hotbars || !data.hotbars.length) {
const hotbar = getEmptyHotbar("Default");
const { metadata: { uid, name, source } } = catalogEntity;
const initialItem = { entity: { uid, name, source } };
const { metadata: { uid, name, source }} = catalogEntity;
const initialItem = { entity: { uid, name, source }};
hotbar.items[0] = initialItem;
@ -99,7 +99,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
toJSON(): HotbarStoreModel {
const model: HotbarStoreModel = {
hotbars: this.hotbars,
activeHotbarId: this.activeHotbarId
activeHotbarId: this.activeHotbarId,
};
return toJS(model);
@ -187,7 +187,7 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
} else if (0 <= cellIndex && cellIndex < hotbar.items.length) {
hotbar.items[cellIndex] = newItem;
} 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[]) {
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
? requestMain(subFramesChannel)
: Promise.resolve(getSubFrames());
subFramesP
.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) {
let viewType = "unknown";

View File

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

View File

@ -119,7 +119,7 @@ describe("Crds", () => {
},
spec: {
version: "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", () => {
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", {
data: {
spec: {
replicas: 5
}
}
replicas: 5,
},
},
},
{
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", {
original: anyObject(),
unknownFields: ["asdjhajksdhadjks"]
unknownFields: ["asdjhajksdhadjks"],
});
console.warn = warn;
});

View File

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

View File

@ -28,11 +28,11 @@ describe("forRemoteCluster", () => {
it("builds api client", async (done) => {
const api = forRemoteCluster({
cluster: {
server: "https://127.0.0.1:6443"
server: "https://127.0.0.1:6443",
},
user: {
token: "daa"
}
token: "daa",
},
}, Pod);
(fetch as any).mockResponse(async (request: any) => {
@ -41,7 +41,7 @@ describe("forRemoteCluster", () => {
done();
return {
body: ""
body: "",
};
});
@ -55,7 +55,7 @@ describe("KubeApi", () => {
beforeEach(() => {
request = new KubeJsonApi({
serverAddress: `http://127.0.0.1:9999`,
apiBase: "/api-kube"
apiBase: "/api-kube",
});
});
@ -65,24 +65,24 @@ describe("KubeApi", () => {
return {
body: JSON.stringify({
resources: [{
name: "ingresses"
}] as any[]
})
name: "ingresses",
}] as any[],
}),
};
} 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
return {
body: JSON.stringify({
resources: [{
name: "ingresses"
}] as any[]
})
name: "ingresses",
}] as any[],
}),
};
} else {
return {
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") {
return {
body: JSON.stringify({
resources: [] as any[]
})
resources: [] as any[],
}),
};
} else if (request.url === "http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1") {
return {
body: JSON.stringify({
resources: [{
name: "ingresses"
}] as any[]
})
name: "ingresses",
}] as any[],
}),
};
} else {
return {
body: JSON.stringify({
resources: [] as any[]
})
resources: [] as any[],
}),
};
}
});

View File

@ -45,12 +45,12 @@ describe("KubeObject", () => {
{
type TestCase = [string, any];
const tests: TestCase[] = [
["kind", { apiVersion: "", metadata: {uid: "", name: "", resourceVersion: "", selfLink: ""} }],
["apiVersion", { kind: "", metadata: {uid: "", name: "", resourceVersion: "", selfLink: ""} }],
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
["metadata", { kind: "", apiVersion: "" }],
["metadata.uid", { kind: "", apiVersion: "", metadata: { name: "", resourceVersion: "", selfLink: ""} }],
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", resourceVersion: "", selfLink: "" } }],
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", selfLink: "" } }],
["metadata.uid", { kind: "", apiVersion: "", metadata: { name: "", resourceVersion: "", selfLink: "" }}],
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", resourceVersion: "", selfLink: "" }}],
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", selfLink: "" }}],
];
it.each(tests)("should reject with missing: %s", (missingField, input) => {
@ -61,23 +61,23 @@ describe("KubeObject", () => {
{
type TestCase = [string, any];
const tests: TestCase[] = [
["kind", { kind: 1, apiVersion: "", metadata: {} }],
["apiVersion", { apiVersion: 1, kind: "", metadata: {} }],
["kind", { kind: 1, apiVersion: "", metadata: {}}],
["apiVersion", { apiVersion: 1, kind: "", metadata: {}}],
["metadata", { kind: "", apiVersion: "", metadata: "" }],
["metadata.uid", { kind: "", apiVersion: "", metadata: { uid: 1 } }],
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", name: 1 } }],
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: 1 } }],
["metadata.selfLink", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: 1 } }],
["metadata.namespace", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", namespace: 1 } }],
["metadata.creationTimestamp", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", creationTimestamp: 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: {} } }],
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: 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: { food: 1 } } }],
["metadata.uid", { kind: "", apiVersion: "", metadata: { uid: 1 }}],
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", name: 1 }}],
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: 1 }}],
["metadata.selfLink", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: 1 }}],
["metadata.namespace", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", namespace: 1 }}],
["metadata.creationTimestamp", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", creationTimestamp: 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: {}}}],
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: 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: { food: 1 }}}],
];
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)", () => {
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);
});
@ -118,8 +118,8 @@ describe("KubeObject", () => {
{
type TestCase = [string, any];
const tests: TestCase[] = [
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" } }],
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" } }],
["kind", { apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
["apiVersion", { kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
["metadata", { kind: "", apiVersion: "" }],
];
@ -131,23 +131,23 @@ describe("KubeObject", () => {
{
type TestCase = [string, any];
const tests: TestCase[] = [
["kind", { kind: 1, apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" } }],
["apiVersion", { apiVersion: 1, kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" } }],
["kind", { kind: 1, apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
["apiVersion", { apiVersion: 1, kind: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "" }}],
["metadata", { kind: "", apiVersion: "", metadata: "" }],
["metadata.uid", { kind: "", apiVersion: "", metadata: { uid: 1, name: "", resourceVersion: "", selfLink: "" } }],
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", name: 1, resourceVersion: "", selfLink: "" } }],
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: 1, selfLink: "" } }],
["metadata.selfLink", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: 1 } }],
["metadata.namespace", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", namespace: 1 } }],
["metadata.creationTimestamp", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", creationTimestamp: 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: {} } }],
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: 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: { food: 1 } } }],
["metadata.uid", { kind: "", apiVersion: "", metadata: { uid: 1, name: "", resourceVersion: "", selfLink: "" }}],
["metadata.name", { kind: "", apiVersion: "", metadata: { uid: "", name: 1, resourceVersion: "", selfLink: "" }}],
["metadata.resourceVersion", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: 1, selfLink: "" }}],
["metadata.selfLink", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: 1 }}],
["metadata.namespace", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", namespace: 1 }}],
["metadata.creationTimestamp", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", creationTimestamp: 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: {}}}],
["metadata.labels", { kind: "", apiVersion: "", metadata: { uid: "", name: "", resourceVersion: "", selfLink: "", labels: 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: { food: 1 }}}],
];
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)", () => {
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);
});
@ -197,8 +197,8 @@ describe("KubeObject", () => {
{
type TestCase = [string, any];
const tests: TestCase[] = [
["kind", { apiVersion: "", items: [], metadata: { resourceVersion: "", selfLink: "" } }],
["apiVersion", { kind: "", items: [], metadata: { resourceVersion: "", selfLink: "" } }],
["kind", { apiVersion: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}],
["apiVersion", { kind: "", items: [], metadata: { resourceVersion: "", selfLink: "" }}],
["metadata", { kind: "", items: [], apiVersion: "" }],
];
@ -210,15 +210,15 @@ describe("KubeObject", () => {
{
type TestCase = [string, any];
const tests: TestCase[] = [
["kind", { kind: 1, items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" } }],
["apiVersion", { kind: "", items: [], apiVersion: 1, metadata: { resourceVersion: "", selfLink: "" } }],
["kind", { kind: 1, items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: "" }}],
["apiVersion", { kind: "", items: [], apiVersion: 1, metadata: { resourceVersion: "", selfLink: "" }}],
["metadata", { kind: "", items: [], apiVersion: "", metadata: 1 }],
["metadata.resourceVersion", { kind: "", items: [], apiVersion: "", metadata: { resourceVersion: 1, selfLink: "" } }],
["metadata.selfLink", { kind: "", items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: 1 } }],
["items", { kind: "", items: 1, 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: "" } }],
["metadata.resourceVersion", { kind: "", items: [], apiVersion: "", metadata: { resourceVersion: 1, selfLink: "" }}],
["metadata.selfLink", { kind: "", items: [], apiVersion: "", metadata: { resourceVersion: "", selfLink: 1 }}],
["items", { kind: "", items: 1, 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: "" }}],
];
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)", () => {
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);
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -117,7 +117,7 @@ export class CustomResourceDefinition extends KubeObject {
params: {
group: this.getGroup(),
name: this.getPluralName(),
}
},
});
}
@ -163,7 +163,7 @@ export class CustomResourceDefinition extends KubeObject {
}
} else if (this.spec.version) {
const { additionalPrinterColumns: apc } = this.spec;
const additionalPrinterColumns = apc?.map(({ JSONPath, ...apc}) => ({ ...apc, jsonPath: JSONPath }));
const additionalPrinterColumns = apc?.map(({ JSONPath, ...apc }) => ({ ...apc, jsonPath: JSONPath }));
return {
name: this.spec.version,
@ -217,7 +217,7 @@ export class CustomResourceDefinition extends KubeObject {
return {
...condition,
isReady: status === "True",
tooltip: `${message || reason} (${lastTransitionTime})`
tooltip: `${message || reason} (${lastTransitionTime})`,
};
});
}
@ -236,5 +236,5 @@ if (isClusterPageContext()) {
}
export {
crdApi
crdApi,
};

View File

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

View File

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

View File

@ -44,14 +44,14 @@ export class DeploymentApi extends KubeApi<Deployment> {
return this.request.patch(this.getScaleApiUrl(params), {
data: {
spec: {
replicas
}
}
replicas,
},
},
},
{
headers: {
"content-type": "application/merge-patch+json"
}
"content-type": "application/merge-patch+json",
},
});
}
@ -61,16 +61,16 @@ export class DeploymentApi extends KubeApi<Deployment> {
spec: {
template: {
metadata: {
annotations: {"kubectl.kubernetes.io/restartedAt" : moment.utc().format()}
}
}
}
}
annotations: { "kubectl.kubernetes.io/restartedAt" : moment.utc().format() },
},
},
},
},
},
{
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: {
replicas: number;
selector: { matchLabels: { [app: string]: string } };
selector: { matchLabels: { [app: string]: string }};
template: {
metadata: {
creationTimestamp?: string;
@ -246,5 +246,5 @@ if (isClusterPageContext()) {
}
export {
deploymentApi
deploymentApi,
};

View File

@ -83,7 +83,7 @@ export class EndpointAddress implements IEndpointAddress {
getTargetRef(): ITargetRef {
if (this.targetRef) {
return Object.assign(this.targetRef, {apiVersion: "v1"});
return Object.assign(this.targetRef, { apiVersion: "v1" });
} else {
return null;
}
@ -159,5 +159,5 @@ if (isClusterPageContext()) {
}
export {
endpointApi
endpointApi,
};

View File

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

View File

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

View File

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

View File

@ -111,7 +111,7 @@ export class HorizontalPodAutoscaler extends KubeObject {
return {
...condition,
isReady: status === "True",
tooltip: `${message || reason} (${lastTransitionTime})`
tooltip: `${message || reason} (${lastTransitionTime})`,
};
});
}
@ -143,7 +143,7 @@ export class HorizontalPodAutoscaler extends KubeObject {
getMetricValues(metric: IHpaMetric): string {
const metricType = metric.type.toLowerCase();
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 target = metric[metricType];
@ -173,5 +173,5 @@ if (isClusterPageContext()) {
}
export {
hpaApi
hpaApi,
};

View File

@ -30,13 +30,13 @@ export class IngressApi extends KubeApi<Ingress> {
}
export function getMetricsForIngress(ingress: string, namespace: string): Promise<IIngressMetrics> {
const opts = { category: "ingress", ingress };
const opts = { category: "ingress", ingress, namespace };
return metricsApi.getMetrics({
bytesSentSuccess: opts,
bytesSentFailure: opts,
requestDurationSeconds: opts,
responseDurationSeconds: opts
responseDurationSeconds: opts,
}, {
namespace,
});
@ -128,7 +128,7 @@ export class Ingress extends KubeObject {
}
getRoutes() {
const { spec: { tls, rules } } = this;
const { spec: { tls, rules }} = this;
if (!rules) return [];
@ -160,12 +160,12 @@ export class Ingress extends KubeObject {
return {
serviceName,
servicePort
servicePort,
};
}
getHosts() {
const { spec: { rules } } = this;
const { spec: { rules }} = this;
if (!rules) return [];
@ -174,7 +174,7 @@ export class Ingress extends KubeObject {
getPorts() {
const ports: number[] = [];
const { spec: { tls, rules, backend, defaultBackend } } = this;
const { spec: { tls, rules, backend, defaultBackend }} = this;
const httpPort = 80;
const tlsPort = 443;
// Note: not using the port name (string)
@ -196,7 +196,7 @@ export class Ingress extends KubeObject {
}
getLoadBalancers() {
const { status: { loadBalancer = { ingress: [] } } } = this;
const { status: { loadBalancer = { ingress: [] }}} = this;
return (loadBalancer.ingress ?? []).map(address => (
address.hostname || address.ip
@ -216,5 +216,5 @@ if (isClusterPageContext()) {
}
export {
ingressApi
ingressApi,
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -30,7 +30,7 @@ export class NodesApi extends KubeApi<Node> {
}
export function getMetricsForAllNodes(): Promise<INodeMetrics> {
const opts = { category: "nodes"};
const opts = { category: "nodes" };
return metricsApi.getMetrics({
memoryUsage: opts,
@ -40,7 +40,7 @@ export function getMetricsForAllNodes(): Promise<INodeMetrics> {
cpuUsage: opts,
cpuCapacity: opts,
fsSize: opts,
fsUsage: opts
fsUsage: opts,
});
}
@ -259,5 +259,5 @@ if (isClusterPageContext()) {
}
export {
nodesApi
nodesApi,
};

View File

@ -35,9 +35,9 @@ export function getMetricsForPvc(pvc: PersistentVolumeClaim): Promise<IPvcMetric
return metricsApi.getMetrics({
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 pod.getVolumes().filter(volume =>
volume.persistentVolumeClaim &&
volume.persistentVolumeClaim.claimName === this.getName()
volume.persistentVolumeClaim.claimName === this.getName(),
).length > 0;
});
}
@ -128,5 +128,5 @@ if (isClusterPageContext()) {
}
export {
pvcApi
pvcApi,
};

View File

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

View File

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

View File

@ -29,7 +29,7 @@ export interface PodDisruptionBudget {
spec: {
minAvailable: string;
maxUnavailable: string;
selector: { matchLabels: { [app: string]: string } };
selector: { matchLabels: { [app: string]: string }};
};
status: {
currentHealthy: number
@ -82,5 +82,5 @@ if (isClusterPageContext()) {
}
export {
pdbApi
pdbApi,
};

View File

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

View File

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

View File

@ -44,9 +44,9 @@ export class ReplicaSetApi extends KubeApi<ReplicaSet> {
data: {
metadata: params,
spec: {
replicas
}
}
replicas,
},
},
});
}
}
@ -78,7 +78,7 @@ export class ReplicaSet extends WorkloadKubeObject {
declare spec: {
replicas?: number;
selector: { matchLabels: { [app: string]: string } };
selector: { matchLabels: { [app: string]: string }};
template?: {
metadata: {
labels: {
@ -133,5 +133,5 @@ if (isClusterPageContext()) {
}
export {
replicaSetApi
replicaSetApi,
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -53,7 +53,7 @@ export interface Service {
clusterIP: string;
clusterIPs?: string[];
externalTrafficPolicy?: string;
externalName: string;
externalName?: string;
loadBalancerIP?: string;
loadBalancerSourceRanges?: string[];
sessionAffinity: string;
@ -100,11 +100,15 @@ export class Service extends KubeObject {
getExternalIps() {
const lb = this.getLoadBalancer();
if (lb && lb.ingress) {
if (lb?.ingress) {
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() {
@ -153,5 +157,5 @@ if (isClusterPageContext()) {
}
export {
serviceApi
serviceApi,
};

View File

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

View File

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

View File

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

View File

@ -57,12 +57,12 @@ export interface JsonApiConfig {
export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
static reqInitDefault: RequestInit = {
headers: {
"content-type": "application/json"
}
"content-type": "application/json",
},
};
static configDefault: Partial<JsonApiConfig> = {
debug: false
debug: false,
};
constructor(public readonly config: JsonApiConfig, protected reqInit?: RequestInit) {
@ -87,7 +87,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
{},
this.reqInit,
await this.getRequestOptions(),
init
init,
);
const { query } = params || {} as P;
@ -126,7 +126,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
{},
this.reqInit,
await this.getRequestOptions(),
init
init,
);
const { data, query } = params || {} as P;
@ -201,7 +201,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
protected writeLog(log: JsonApiLog) {
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,
}, {
headers: {
"Host": `${cluster.metadata.uid}.localhost:${url.port}`
}
"Host": `${cluster.metadata.uid}.localhost:${url.port}`,
},
});
return new KubeApi({
objectConstructor: kubeClass,
request
request,
});
}
@ -166,15 +166,15 @@ export function forRemoteCluster<T extends KubeObject>(config: IRemoteKubeApiCon
...(token ? {
getRequestOptions: async () => ({
headers: {
"Authorization": `Bearer ${isFunction(token) ? await token() : token}`
}
})
} : {})
"Authorization": `Bearer ${isFunction(token) ? await token() : token}`,
},
}),
} : {}),
}, reqInit);
return new KubeApi({
objectConstructor: kubeClass,
request
request,
});
}
@ -221,7 +221,7 @@ export class KubeApi<T extends KubeObject> {
objectConstructor,
request = apiKube,
kind = options.objectConstructor?.kind,
isNamespaced = options.objectConstructor?.namespaced
isNamespaced = options.objectConstructor?.namespaced,
} = options || {};
if (!options.apiBase) {
@ -292,7 +292,7 @@ export class KubeApi<T extends KubeObject> {
return {
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
Object.defineProperty(this, "apiPrefix", {
value: apiPrefix
value: apiPrefix,
});
Object.defineProperty(this, "apiGroup", {
value: apiGroup
value: 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,
metadata: {
name,
namespace
}
}, data)
namespace,
},
}, data),
});
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) {
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({
namespace,
abortController,
callback
callback,
});
const { signal } = abortController;
@ -375,8 +375,8 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
timedRetry = setTimeout(() => {
(
namespace
? this.loadAll({ namespaces: [namespace], reqInit: { signal } })
: this.loadAll({ merge: false, reqInit: { signal } })
? this.loadAll({ namespaces: [namespace], reqInit: { signal }})
: this.loadAll({ merge: false, reqInit: { signal }})
).then(watch);
}, 1000);
} 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 {
const { preload = true, waitUntilLoaded = true, loadOnce = false, } = opts;
const { preload = true, waitUntilLoaded = true, loadOnce = false } = opts;
const subscribingNamespaces = opts.namespaces ?? this.context?.allNamespaces ?? [];
const unsubscribeList: Function[] = [];
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) {
return;
}

View File

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

View File

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

View File

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

View File

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

View File

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

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