diff --git a/.eslintrc.js b/.eslintrc.js
index e50982d63a..913430d291 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,4 +1,4 @@
-module.exports = {
+module.exports = {
ignorePatterns: ["src/extensions/npm/extensions/dist/**/*"],
overrides: [
{
@@ -13,12 +13,14 @@ module.exports = {
env: {
node: true
},
- parserOptions: {
+ parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
rules: {
- "indent": ["error", 2],
+ "indent": ["error", 2, {
+ "SwitchCase": 1,
+ }],
"no-unused-vars": "off",
"semi": ["error", "always"],
}
@@ -33,10 +35,10 @@ module.exports = {
"__mocks__/*.ts",
],
parser: "@typescript-eslint/parser",
- extends: [
+ extends: [
'plugin:@typescript-eslint/recommended',
],
- parserOptions: {
+ parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
@@ -48,7 +50,9 @@ module.exports = {
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-empty-interface": "off",
- "indent": ["error", 2],
+ "indent": ["error", 2, {
+ "SwitchCase": 1,
+ }],
"semi": "off",
"@typescript-eslint/semi": ["error"],
},
@@ -58,10 +62,10 @@ module.exports = {
"src/renderer/**/*.tsx",
],
parser: "@typescript-eslint/parser",
- extends: [
+ extends: [
'plugin:@typescript-eslint/recommended',
],
- parserOptions: {
+ parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
jsx: true,
@@ -78,7 +82,9 @@ module.exports = {
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/ban-types": "off",
"@typescript-eslint/no-empty-function": "off",
- "indent": ["error", 2],
+ "indent": ["error", 2, {
+ "SwitchCase": 1,
+ }],
"semi": "off",
"@typescript-eslint/semi": ["error"],
},
diff --git a/src/extensions/registries/page-menu-registry.ts b/src/extensions/registries/page-menu-registry.ts
index 15f11139e6..53131f507b 100644
--- a/src/extensions/registries/page-menu-registry.ts
+++ b/src/extensions/registries/page-menu-registry.ts
@@ -1,9 +1,10 @@
// Extensions-api -> Register page menu items
import type { IconProps } from "../../renderer/components/icon";
import type React from "react";
-import { action } from "mobx";
+import { action, computed } from "mobx";
import { BaseRegistry } from "./base-registry";
import { LensExtension } from "../lens-extension";
+import { RegisteredPage } from "./page-registry";
export interface PageMenuTarget
{
extensionId?: string;
@@ -17,11 +18,16 @@ export interface PageMenuRegistration {
components: PageMenuComponents;
}
+export interface ClusterPageMenuRegistration extends PageMenuRegistration {
+ id?: string;
+ parentId?: string;
+}
+
export interface PageMenuComponents {
Icon: React.ComponentType;
}
-export class PageMenuRegistry extends BaseRegistry> {
+export class GlobalPageMenuRegistry extends BaseRegistry {
@action
add(items: PageMenuRegistration[], ext: LensExtension) {
const normalizedItems = items.map(menuItem => {
@@ -35,5 +41,31 @@ export class PageMenuRegistry extends BaseRegistry {
+ @action
+ add(items: PageMenuRegistration[], ext: LensExtension) {
+ const normalizedItems = items.map(menuItem => {
+ menuItem.target = {
+ extensionId: ext.name,
+ ...(menuItem.target || {}),
+ };
+ return menuItem;
+ });
+ return super.add(normalizedItems);
+ }
+
+ getRootItems() {
+ return this.getItems().filter((item) => !item.parentId);
+ }
+
+ getSubItems(parent: ClusterPageMenuRegistration) {
+ return this.getItems().filter((item) => item.parentId === parent.id && item.target.extensionId === parent.target.extensionId);
+ }
+
+ getByPage(page: RegisteredPage) {
+ return this.getItems().find((item) => item.target?.pageId == page.id && item.target?.extensionId === page.extensionId);
+ }
+}
+
+export const globalPageMenuRegistry = new GlobalPageMenuRegistry();
+export const clusterPageMenuRegistry = new ClusterPageMenuRegistry();
diff --git a/src/main/prometheus/lens.ts b/src/main/prometheus/lens.ts
index 76a459212d..33126220de 100644
--- a/src/main/prometheus/lens.ts
+++ b/src/main/prometheus/lens.ts
@@ -24,60 +24,60 @@ export class PrometheusLens implements PrometheusProvider {
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
switch(opts.category) {
- case 'cluster':
- return {
- memoryUsage: `
+ case 'cluster':
+ return {
+ memoryUsage: `
sum(
node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)
) by (kubernetes_name)
`.replace(/_bytes/g, `_bytes{kubernetes_node=~"${opts.nodes}"}`),
- memoryRequests: `sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="memory"}) by (component)`,
- memoryLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="memory"}) by (component)`,
- memoryCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="memory"}) by (component)`,
- cpuUsage: `sum(rate(node_cpu_seconds_total{kubernetes_node=~"${opts.nodes}", mode=~"user|system"}[${this.rateAccuracy}]))`,
- cpuRequests:`sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
- cpuLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
- cpuCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
- podUsage: `sum(kubelet_running_pod_count{instance=~"${opts.nodes}"})`,
- podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"}) by (component)`,
- fsSize: `sum(node_filesystem_size_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"}) by (kubernetes_node)`,
- fsUsage: `sum(node_filesystem_size_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"} - node_filesystem_avail_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"}) by (kubernetes_node)`
- };
- case 'nodes':
- return {
- memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (kubernetes_node)`,
- memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
- cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}])) by(kubernetes_node)`,
- cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`,
- fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"}) by (kubernetes_node)`,
- fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) by (kubernetes_node)`
- };
- case 'pods':
- return {
- cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
- cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
- cpuLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
- memoryUsage: `sum(container_memory_working_set_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
- memoryRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
- memoryLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
- fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
- networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
- networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
- };
- case 'pvc':
- return {
- diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
- diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
- };
- case 'ingress':
- const bytesSent = (ingress: string, statuses: string) =>
- `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
- return {
- bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
- bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
- requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
- responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
- };
+ memoryRequests: `sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="memory"}) by (component)`,
+ memoryLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="memory"}) by (component)`,
+ memoryCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="memory"}) by (component)`,
+ cpuUsage: `sum(rate(node_cpu_seconds_total{kubernetes_node=~"${opts.nodes}", mode=~"user|system"}[${this.rateAccuracy}]))`,
+ cpuRequests:`sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
+ cpuLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
+ cpuCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
+ podUsage: `sum(kubelet_running_pod_count{instance=~"${opts.nodes}"})`,
+ podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"}) by (component)`,
+ fsSize: `sum(node_filesystem_size_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"}) by (kubernetes_node)`,
+ fsUsage: `sum(node_filesystem_size_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"} - node_filesystem_avail_bytes{kubernetes_node=~"${opts.nodes}", mountpoint="/"}) by (kubernetes_node)`
+ };
+ case 'nodes':
+ return {
+ memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (kubernetes_node)`,
+ memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
+ cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}])) by(kubernetes_node)`,
+ cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`,
+ fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"}) by (kubernetes_node)`,
+ fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) by (kubernetes_node)`
+ };
+ case 'pods':
+ return {
+ cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
+ cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ cpuLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ memoryUsage: `sum(container_memory_working_set_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ memoryRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ memoryLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
+ networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
+ };
+ case 'pvc':
+ return {
+ diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
+ diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
+ };
+ case 'ingress':
+ const bytesSent = (ingress: string, statuses: string) =>
+ `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
+ return {
+ bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
+ bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
+ requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
+ responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
+ };
}
}
}
diff --git a/src/main/prometheus/operator.ts b/src/main/prometheus/operator.ts
index 8e27a4a6f3..ef9f530299 100644
--- a/src/main/prometheus/operator.ts
+++ b/src/main/prometheus/operator.ts
@@ -32,60 +32,60 @@ export class PrometheusOperator implements PrometheusProvider {
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
switch(opts.category) {
- case 'cluster':
- return {
- memoryUsage: `
+ case 'cluster':
+ return {
+ memoryUsage: `
sum(
node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)
)
`.replace(/_bytes/g, `_bytes * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"}`),
- memoryRequests: `sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="memory"})`,
- memoryLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="memory"})`,
- memoryCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="memory"})`,
- cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}])* on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`,
- cpuRequests:`sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="cpu"})`,
- cpuLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="cpu"})`,
- cpuCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="cpu"})`,
- podUsage: `sum(kubelet_running_pod_count{node=~"${opts.nodes}"})`,
- podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"})`,
- fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`,
- fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"} - node_filesystem_avail_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`
- };
- case 'nodes':
- return {
- memoryUsage: `sum((node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
- memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
- cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}]) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
- cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`,
- fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
- fsUsage: `sum((node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`
- };
- case 'pods':
- return {
- cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",image!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
- cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
- cpuLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
- memoryUsage: `sum(container_memory_working_set_bytes{container!="POD",container!="",image!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
- memoryRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
- memoryLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
- fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
- networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
- networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
- };
- case 'pvc':
- return {
- diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
- diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
- };
- case 'ingress':
- const bytesSent = (ingress: string, statuses: string) =>
- `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
- return {
- bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
- bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
- requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
- responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
- };
+ memoryRequests: `sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="memory"})`,
+ memoryLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="memory"})`,
+ memoryCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="memory"})`,
+ cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}])* on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`,
+ cpuRequests:`sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="cpu"})`,
+ cpuLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="cpu"})`,
+ cpuCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="cpu"})`,
+ podUsage: `sum(kubelet_running_pod_count{node=~"${opts.nodes}"})`,
+ podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"})`,
+ fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`,
+ fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"} - node_filesystem_avail_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info{node=~"${opts.nodes}"})`
+ };
+ case 'nodes':
+ return {
+ memoryUsage: `sum((node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
+ memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
+ cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}]) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
+ cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`,
+ fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"} * on (pod,namespace) group_left(node) kube_pod_info) by (node)`,
+ fsUsage: `sum((node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) * on (pod,namespace) group_left(node) kube_pod_info) by (node)`
+ };
+ case 'pods':
+ return {
+ cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",image!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
+ cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ cpuLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ memoryUsage: `sum(container_memory_working_set_bytes{container!="POD",container!="",image!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ memoryRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ memoryLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
+ networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
+ };
+ case 'pvc':
+ return {
+ diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
+ diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
+ };
+ case 'ingress':
+ const bytesSent = (ingress: string, statuses: string) =>
+ `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
+ return {
+ bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
+ bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
+ requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
+ responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
+ };
}
}
}
diff --git a/src/main/prometheus/stacklight.ts b/src/main/prometheus/stacklight.ts
index 35394336d3..bd23dd63cf 100644
--- a/src/main/prometheus/stacklight.ts
+++ b/src/main/prometheus/stacklight.ts
@@ -24,60 +24,60 @@ export class PrometheusStacklight implements PrometheusProvider {
public getQueries(opts: PrometheusQueryOpts): PrometheusQuery {
switch(opts.category) {
- case 'cluster':
- return {
- memoryUsage: `
+ case 'cluster':
+ return {
+ memoryUsage: `
sum(
node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)
) by (kubernetes_name)
`.replace(/_bytes/g, `_bytes{node=~"${opts.nodes}"}`),
- memoryRequests: `sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="memory"}) by (component)`,
- memoryLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="memory"}) by (component)`,
- memoryCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="memory"}) by (component)`,
- cpuUsage: `sum(rate(node_cpu_seconds_total{node=~"${opts.nodes}", mode=~"user|system"}[${this.rateAccuracy}]))`,
- cpuRequests:`sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
- cpuLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
- cpuCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
- podUsage: `sum(kubelet_running_pod_count{instance=~"${opts.nodes}"})`,
- podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"}) by (component)`,
- fsSize: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`,
- fsUsage: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"} - node_filesystem_avail_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`
- };
- case 'nodes':
- return {
- memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (node)`,
- memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
- cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}])) by(node)`,
- cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`,
- fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"}) by (node)`,
- fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) by (node)`
- };
- case 'pods':
- return {
- cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
- cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
- cpuLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
- memoryUsage: `sum(container_memory_working_set_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
- memoryRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
- memoryLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
- fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
- networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
- networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
- };
- case 'pvc':
- return {
- diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
- diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
- };
- case 'ingress':
- const bytesSent = (ingress: string, statuses: string) =>
- `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
- return {
- bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
- bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
- requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
- responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
- };
+ memoryRequests: `sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="memory"}) by (component)`,
+ memoryLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="memory"}) by (component)`,
+ memoryCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="memory"}) by (component)`,
+ cpuUsage: `sum(rate(node_cpu_seconds_total{node=~"${opts.nodes}", mode=~"user|system"}[${this.rateAccuracy}]))`,
+ cpuRequests:`sum(kube_pod_container_resource_requests{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
+ cpuLimits: `sum(kube_pod_container_resource_limits{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
+ cpuCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="cpu"}) by (component)`,
+ podUsage: `sum(kubelet_running_pod_count{instance=~"${opts.nodes}"})`,
+ podCapacity: `sum(kube_node_status_capacity{node=~"${opts.nodes}", resource="pods"}) by (component)`,
+ fsSize: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`,
+ fsUsage: `sum(node_filesystem_size_bytes{node=~"${opts.nodes}", mountpoint="/"} - node_filesystem_avail_bytes{node=~"${opts.nodes}", mountpoint="/"}) by (node)`
+ };
+ case 'nodes':
+ return {
+ memoryUsage: `sum (node_memory_MemTotal_bytes - (node_memory_MemFree_bytes + node_memory_Buffers_bytes + node_memory_Cached_bytes)) by (node)`,
+ memoryCapacity: `sum(kube_node_status_capacity{resource="memory"}) by (node)`,
+ cpuUsage: `sum(rate(node_cpu_seconds_total{mode=~"user|system"}[${this.rateAccuracy}])) by(node)`,
+ cpuCapacity: `sum(kube_node_status_allocatable{resource="cpu"}) by (node)`,
+ fsSize: `sum(node_filesystem_size_bytes{mountpoint="/"}) by (node)`,
+ fsUsage: `sum(node_filesystem_size_bytes{mountpoint="/"} - node_filesystem_avail_bytes{mountpoint="/"}) by (node)`
+ };
+ case 'pods':
+ return {
+ cpuUsage: `sum(rate(container_cpu_usage_seconds_total{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
+ cpuRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ cpuLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="cpu",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ memoryUsage: `sum(container_memory_working_set_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ memoryRequests: `sum(kube_pod_container_resource_requests{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ memoryLimits: `sum(kube_pod_container_resource_limits{pod=~"${opts.pods}",resource="memory",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ fsUsage: `sum(container_fs_usage_bytes{container!="POD",container!="",pod=~"${opts.pods}",namespace="${opts.namespace}"}) by (${opts.selector})`,
+ networkReceive: `sum(rate(container_network_receive_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`,
+ networkTransmit: `sum(rate(container_network_transmit_bytes_total{pod=~"${opts.pods}",namespace="${opts.namespace}"}[${this.rateAccuracy}])) by (${opts.selector})`
+ };
+ case 'pvc':
+ return {
+ diskUsage: `sum(kubelet_volume_stats_used_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`,
+ diskCapacity: `sum(kubelet_volume_stats_capacity_bytes{persistentvolumeclaim="${opts.pvc}"}) by (persistentvolumeclaim, namespace)`
+ };
+ case 'ingress':
+ const bytesSent = (ingress: string, statuses: string) =>
+ `sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
+ return {
+ bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
+ bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
+ requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
+ responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
+ };
}
}
}
diff --git a/src/main/shell-session.ts b/src/main/shell-session.ts
index 42e0039047..23a163b341 100644
--- a/src/main/shell-session.ts
+++ b/src/main/shell-session.ts
@@ -70,16 +70,16 @@ export class ShellSession extends EventEmitter {
protected async getShellArgs(shell: string): Promise> {
switch(path.basename(shell)) {
- case "powershell.exe":
- return ["-NoExit", "-command", `& {Set-Location $Env:USERPROFILE; $Env:PATH="${this.helmBinDir};${this.kubectlPathDir};$Env:PATH"}`];
- case "bash":
- return ["--init-file", path.join(this.kubectlBinDir, '.bash_set_path')];
- case "fish":
- return ["--login", "--init-command", `export PATH="${this.helmBinDir}:${this.kubectlPathDir}:$PATH"; export KUBECONFIG="${this.kubeconfigPath}"`];
- case "zsh":
- return ["--login"];
- default:
- return [];
+ case "powershell.exe":
+ return ["-NoExit", "-command", `& {Set-Location $Env:USERPROFILE; $Env:PATH="${this.helmBinDir};${this.kubectlPathDir};$Env:PATH"}`];
+ case "bash":
+ return ["--init-file", path.join(this.kubectlBinDir, '.bash_set_path')];
+ case "fish":
+ return ["--login", "--init-command", `export PATH="${this.helmBinDir}:${this.kubectlPathDir}:$PATH"; export KUBECONFIG="${this.kubeconfigPath}"`];
+ case "zsh":
+ return ["--login"];
+ default:
+ return [];
}
}
@@ -148,16 +148,16 @@ export class ShellSession extends EventEmitter {
const message = Buffer.from(data.slice(1, data.length), "base64").toString();
switch (data[0]) {
- case "0":
- this.shellProcess.write(message);
- break;
- case "4":
- const resizeMsgObj = JSON.parse(message);
- this.shellProcess.resize(resizeMsgObj["Width"], resizeMsgObj["Height"]);
- break;
- case "9":
- this.emit('newToken', message);
- break;
+ case "0":
+ this.shellProcess.write(message);
+ break;
+ case "4":
+ const resizeMsgObj = JSON.parse(message);
+ this.shellProcess.resize(resizeMsgObj["Width"], resizeMsgObj["Height"]);
+ break;
+ case "9":
+ this.emit('newToken', message);
+ break;
}
});
}
diff --git a/src/renderer/api/endpoints/hpa.api.ts b/src/renderer/api/endpoints/hpa.api.ts
index 79e6cada0f..657e34e38c 100644
--- a/src/renderer/api/endpoints/hpa.api.ts
+++ b/src/renderer/api/endpoints/hpa.api.ts
@@ -101,14 +101,14 @@ export class HorizontalPodAutoscaler extends KubeObject {
protected getMetricName(metric: IHpaMetric): string {
const { type, resource, pods, object, external } = metric;
switch (type) {
- case HpaMetricType.Resource:
- return resource.name;
- case HpaMetricType.Pods:
- return pods.metricName;
- case HpaMetricType.Object:
- return object.metricName;
- case HpaMetricType.External:
- return external.metricName;
+ case HpaMetricType.Resource:
+ return resource.name;
+ case HpaMetricType.Pods:
+ return pods.metricName;
+ case HpaMetricType.Object:
+ return object.metricName;
+ case HpaMetricType.External:
+ return external.metricName;
}
}
diff --git a/src/renderer/api/index.ts b/src/renderer/api/index.ts
index 7dd2306e74..1a82ce45f8 100644
--- a/src/renderer/api/index.ts
+++ b/src/renderer/api/index.ts
@@ -15,10 +15,10 @@ export const apiKube = new KubeJsonApi({
// Common handler for HTTP api errors
export function onApiError(error: JsonApiErrorParsed, res: Response) {
switch (res.status) {
- case 403:
- error.isUsedForNotification = true;
- Notifications.error(error);
- break;
+ case 403:
+ error.isUsedForNotification = true;
+ Notifications.error(error);
+ break;
}
}
diff --git a/src/renderer/api/kube-api-parse.ts b/src/renderer/api/kube-api-parse.ts
index 0995fac24f..5d7ad091ee 100644
--- a/src/renderer/api/kube-api-parse.ts
+++ b/src/renderer/api/kube-api-parse.ts
@@ -35,32 +35,32 @@ export function parseKubeApi(path: string): IKubeApiParsed {
if (namespaced) {
switch (right.length) {
- case 1:
- name = right[0];
+ case 1:
+ name = right[0];
// fallthrough
- case 0:
- resource = "namespaces"; // special case this due to `split` removing namespaces
- break;
- default:
- [namespace, resource, name] = right;
- break;
+ case 0:
+ resource = "namespaces"; // special case this due to `split` removing namespaces
+ break;
+ default:
+ [namespace, resource, name] = right;
+ break;
}
apiVersion = left.pop();
apiGroup = left.join("/");
} else {
switch (left.length) {
- case 4:
- [apiGroup, apiVersion, resource, name] = left;
- break;
- case 2:
- resource = left.pop();
+ case 4:
+ [apiGroup, apiVersion, resource, name] = left;
+ break;
+ case 2:
+ resource = left.pop();
// fallthrough
- case 1:
- apiVersion = left.pop();
- apiGroup = "";
- break;
- default:
+ case 1:
+ apiVersion = left.pop();
+ apiGroup = "";
+ break;
+ default:
/**
* Given that
* - `apiVersion` is `GROUP/VERSION` and
@@ -77,15 +77,15 @@ export function parseKubeApi(path: string): IKubeApiParsed {
* 3. otherwise assume apiVersion <- left[0]
* 4. always resource, name <- left[(0 or 1)+1..]
*/
- if (left[0].includes('.') || left[1].match(/^v[0-9]/)) {
- [apiGroup, apiVersion] = left;
- resource = left.slice(2).join("/");
- } else {
- apiGroup = "";
- apiVersion = left[0];
- [resource, name] = left.slice(1);
- }
- break;
+ if (left[0].includes('.') || left[1].match(/^v[0-9]/)) {
+ [apiGroup, apiVersion] = left;
+ resource = left.slice(2).join("/");
+ } else {
+ apiGroup = "";
+ apiVersion = left[0];
+ [resource, name] = left.slice(1);
+ }
+ break;
}
}
diff --git a/src/renderer/components/+add-cluster/add-cluster.tsx b/src/renderer/components/+add-cluster/add-cluster.tsx
index ef9fb5c43c..f77d3c1959 100644
--- a/src/renderer/components/+add-cluster/add-cluster.tsx
+++ b/src/renderer/components/+add-cluster/add-cluster.tsx
@@ -77,19 +77,19 @@ export class AddCluster extends React.Component {
this.kubeContexts.clear();
switch (this.sourceTab) {
- case KubeConfigSourceTab.FILE:
- const contexts = this.getContexts(this.kubeConfigLocal);
- this.kubeContexts.replace(contexts);
- break;
- case KubeConfigSourceTab.TEXT:
- try {
- this.error = "";
- const contexts = this.getContexts(loadConfig(this.customConfig || "{}"));
+ case KubeConfigSourceTab.FILE:
+ const contexts = this.getContexts(this.kubeConfigLocal);
this.kubeContexts.replace(contexts);
- } catch (err) {
- this.error = String(err);
- }
- break;
+ break;
+ case KubeConfigSourceTab.TEXT:
+ try {
+ this.error = "";
+ const contexts = this.getContexts(loadConfig(this.customConfig || "{}"));
+ this.kubeContexts.replace(contexts);
+ } catch (err) {
+ this.error = String(err);
+ }
+ break;
}
if (this.kubeContexts.size === 1) {
diff --git a/src/renderer/components/+cluster/cluster.store.ts b/src/renderer/components/+cluster/cluster.store.ts
index 63d8f07b3b..052b52fb29 100644
--- a/src/renderer/components/+cluster/cluster.store.ts
+++ b/src/renderer/components/+cluster/cluster.store.ts
@@ -84,12 +84,12 @@ export class ClusterStore extends KubeObjectStore {
getMetricsValues(source: Partial): [number, string][] {
switch (this.metricType) {
- case MetricType.CPU:
- return normalizeMetrics(source.cpuUsage).data.result[0].values;
- case MetricType.MEMORY:
- return normalizeMetrics(source.memoryUsage).data.result[0].values;
- default:
- return [];
+ case MetricType.CPU:
+ return normalizeMetrics(source.cpuUsage).data.result[0].values;
+ case MetricType.MEMORY:
+ return normalizeMetrics(source.memoryUsage).data.result[0].values;
+ default:
+ return [];
}
}
diff --git a/src/renderer/components/+config-autoscalers/hpa-details.tsx b/src/renderer/components/+config-autoscalers/hpa-details.tsx
index b068c28361..5b4dad1fa3 100644
--- a/src/renderer/components/+config-autoscalers/hpa-details.tsx
+++ b/src/renderer/components/+config-autoscalers/hpa-details.tsx
@@ -26,30 +26,30 @@ export class HpaDetails extends React.Component {
const renderName = (metric: IHpaMetric) => {
switch (metric.type) {
- case HpaMetricType.Resource:
- const addition = metric.resource.targetAverageUtilization ? (as a percentage of request) : "";
- return Resource {metric.resource.name} on Pods {addition};
+ case HpaMetricType.Resource:
+ const addition = metric.resource.targetAverageUtilization ? (as a percentage of request) : "";
+ return Resource {metric.resource.name} on Pods {addition};
- case HpaMetricType.Pods:
- return {metric.pods.metricName} on Pods;
+ case HpaMetricType.Pods:
+ return {metric.pods.metricName} on Pods;
- case HpaMetricType.Object:
- const { target } = metric.object;
- const { kind, name } = target;
- const objectUrl = getDetailsUrl(lookupApiLink(target, hpa));
- return (
-
- {metric.object.metricName} on{" "}
- {kind}/{name}
-
- );
- case HpaMetricType.External:
- return (
-
- {metric.external.metricName} on{" "}
- {JSON.stringify(metric.external.selector)}
-
- );
+ case HpaMetricType.Object:
+ const { target } = metric.object;
+ const { kind, name } = target;
+ const objectUrl = getDetailsUrl(lookupApiLink(target, hpa));
+ return (
+
+ {metric.object.metricName} on{" "}
+ {kind}/{name}
+
+ );
+ case HpaMetricType.External:
+ return (
+
+ {metric.external.metricName} on{" "}
+ {JSON.stringify(metric.external.selector)}
+
+ );
}
};
diff --git a/src/renderer/components/+config-resource-quotas/add-quota-dialog.tsx b/src/renderer/components/+config-resource-quotas/add-quota-dialog.tsx
index 3759958750..534c494268 100644
--- a/src/renderer/components/+config-resource-quotas/add-quota-dialog.tsx
+++ b/src/renderer/components/+config-resource-quotas/add-quota-dialog.tsx
@@ -117,10 +117,10 @@ export class AddQuotaDialog extends React.Component {
onInputQuota = (evt: React.KeyboardEvent) => {
switch (evt.key) {
- case "Enter":
- this.setQuota();
- evt.preventDefault(); // don't submit form
- break;
+ case "Enter":
+ this.setQuota();
+ evt.preventDefault(); // don't submit form
+ break;
}
};
diff --git a/src/renderer/components/ace-editor/ace-editor.tsx b/src/renderer/components/ace-editor/ace-editor.tsx
index eb1d71b106..36e80dc81a 100644
--- a/src/renderer/components/ace-editor/ace-editor.tsx
+++ b/src/renderer/components/ace-editor/ace-editor.tsx
@@ -58,10 +58,10 @@ export class AceEditor extends React.Component {
get theme() {
switch (themeStore.activeTheme.type) {
- case "light":
- return "dreamweaver";
- case "dark":
- return "terminal";
+ case "light":
+ return "dreamweaver";
+ case "dark":
+ return "terminal";
}
}
diff --git a/src/renderer/components/app.tsx b/src/renderer/components/app.tsx
index 185a9650fa..7aea1125ad 100755
--- a/src/renderer/components/app.tsx
+++ b/src/renderer/components/app.tsx
@@ -34,12 +34,15 @@ import { Terminal } from "./dock/terminal";
import { getHostedCluster, getHostedClusterId } from "../../common/cluster-store";
import logger from "../../main/logger";
import { webFrame } from "electron";
-import { clusterPageRegistry } from "../../extensions/registries/page-registry";
+import { clusterPageRegistry, getExtensionPageUrl, PageRegistration, RegisteredPage } from "../../extensions/registries/page-registry";
import { extensionLoader } from "../../extensions/extension-loader";
import { appEventBus } from "../../common/event-bus";
import { requestMain } from "../../common/ipc";
import whatInput from 'what-input';
import { clusterSetFrameIdHandler } from "../../common/cluster-ipc";
+import { ClusterPageMenuRegistration, clusterPageMenuRegistry } from "../../extensions/registries";
+import { TabLayoutRoute, TabLayout } from "./layout/tab-layout";
+import { Trans } from "@lingui/macro";
@observer
export class App extends React.Component {
@@ -72,9 +75,48 @@ export class App extends React.Component {
return workloadsURL();
}
+ getTabLayoutRoutes(menuItem: ClusterPageMenuRegistration) {
+ const routes: TabLayoutRoute[] = [];
+ if (!menuItem.id) {
+ return routes;
+ }
+ clusterPageMenuRegistry.getSubItems(menuItem).forEach((item) => {
+ const page = clusterPageRegistry.getByPageMenuTarget(item.target);
+ if (page) {
+ routes.push({
+ routePath: page.routePath,
+ url: getExtensionPageUrl({ extensionId: page.extensionId, pageId: page.id, params: item.target.params }),
+ title: item.title,
+ component: page.components.Page,
+ exact: page.exact
+ });
+ }
+ });
+ return routes;
+ }
+
+ renderExtensionTabLayoutRoutes() {
+ return clusterPageMenuRegistry.getRootItems().map((menu, index) => {
+ const tabRoutes = this.getTabLayoutRoutes(menu);
+ if (tabRoutes.length > 0) {
+ const pageComponent = () => ;
+ return ;
+ } else {
+ const page = clusterPageRegistry.getByPageMenuTarget(menu.target);
+ if (page) {
+ const pageComponent = () => ;
+ return ;
+ }
+ }
+ });
+ }
+
renderExtensionRoutes() {
- return clusterPageRegistry.getItems().map(({ components: { Page }, exact, routePath }) => {
- return ;
+ return clusterPageRegistry.getItems().map((page, index) => {
+ const menu = clusterPageMenuRegistry.getByPage(page);
+ if (!menu) {
+ return ;
+ }
});
}
@@ -96,6 +138,7 @@ export class App extends React.Component {
+ {this.renderExtensionTabLayoutRoutes()}
{this.renderExtensionRoutes()}
diff --git a/src/renderer/components/dock/terminal.ts b/src/renderer/components/dock/terminal.ts
index d0009f3c8b..67a4f88168 100644
--- a/src/renderer/components/dock/terminal.ts
+++ b/src/renderer/components/dock/terminal.ts
@@ -173,14 +173,14 @@ export class Terminal {
if (ctrlKey) {
switch (code) {
// Ctrl+C: prevent terminal exit on windows / linux (?)
- case "KeyC":
- if (this.xterm.hasSelection()) return false;
- break;
+ case "KeyC":
+ if (this.xterm.hasSelection()) return false;
+ break;
- // Ctrl+W: prevent unexpected terminal tab closing, e.g. editing file in vim
- case "KeyW":
- evt.preventDefault();
- break;
+ // Ctrl+W: prevent unexpected terminal tab closing, e.g. editing file in vim
+ case "KeyW":
+ evt.preventDefault();
+ break;
}
}
diff --git a/src/renderer/components/file-picker/file-picker.tsx b/src/renderer/components/file-picker/file-picker.tsx
index 1fcd26f766..4f9a07c0cf 100644
--- a/src/renderer/components/file-picker/file-picker.tsx
+++ b/src/renderer/components/file-picker/file-picker.tsx
@@ -85,11 +85,11 @@ export class FilePicker extends React.Component {
const { limit: [minLimit, maxLimit] = [0, Infinity], onOverLimit } = this.props;
if (files.length > maxLimit) {
switch (onOverLimit) {
- case OverLimitStyle.CAP:
- files.length = maxLimit;
- break;
- case OverLimitStyle.REJECT:
- throw `Too many files. Expected at most ${maxLimit}. Got ${files.length}.`;
+ case OverLimitStyle.CAP:
+ files.length = maxLimit;
+ break;
+ case OverLimitStyle.REJECT:
+ throw `Too many files. Expected at most ${maxLimit}. Got ${files.length}.`;
}
}
if (files.length < minLimit) {
@@ -103,15 +103,15 @@ export class FilePicker extends React.Component {
const { onOverSizeLimit, maxSize } = this.props;
switch (onOverSizeLimit) {
- case OverSizeLimitStyle.FILTER:
- return files.filter(file => file.size <= maxSize );
- case OverSizeLimitStyle.REJECT:
- const firstFileToLarge = files.find(file => file.size > maxSize);
- if (firstFileToLarge) {
- throw `${firstFileToLarge.name} is too large. Maximum size is ${maxSize}. Has size of ${firstFileToLarge.size}`;
- }
+ case OverSizeLimitStyle.FILTER:
+ return files.filter(file => file.size <= maxSize );
+ case OverSizeLimitStyle.REJECT:
+ const firstFileToLarge = files.find(file => file.size > maxSize);
+ if (firstFileToLarge) {
+ throw `${firstFileToLarge.name} is too large. Maximum size is ${maxSize}. Has size of ${firstFileToLarge.size}`;
+ }
- return files;
+ return files;
}
}
@@ -124,20 +124,20 @@ export class FilePicker extends React.Component {
}
switch (onOverTotalSizeLimit) {
- case OverTotalSizeLimitStyle.FILTER_LARGEST:
- files = _.orderBy(files, ["size"]);
- case OverTotalSizeLimitStyle.FILTER_LAST:
- let newTotalSize = totalSize;
+ case OverTotalSizeLimitStyle.FILTER_LARGEST:
+ files = _.orderBy(files, ["size"]);
+ case OverTotalSizeLimitStyle.FILTER_LAST:
+ let newTotalSize = totalSize;
- for (;files.length > 0;) {
- newTotalSize -= files.pop().size;
- if (newTotalSize <= maxTotalSize) {
- break;
+ for (;files.length > 0;) {
+ newTotalSize -= files.pop().size;
+ if (newTotalSize <= maxTotalSize) {
+ break;
+ }
}
- }
- return files;
- case OverTotalSizeLimitStyle.REJECT:
- throw `Total file size to upload is too large. Expected at most ${maxTotalSize}. Found ${totalSize}.`;
+ return files;
+ case OverTotalSizeLimitStyle.REJECT:
+ throw `Total file size to upload is too large. Expected at most ${maxTotalSize}. Found ${totalSize}.`;
}
}
@@ -192,12 +192,12 @@ export class FilePicker extends React.Component {
getIconRight(): React.ReactNode {
switch (this.status) {
- case FileInputStatus.CLEAR:
- return ;
- case FileInputStatus.PROCESSING:
- return ;
- case FileInputStatus.ERROR:
- return ;
+ case FileInputStatus.CLEAR:
+ return ;
+ case FileInputStatus.PROCESSING:
+ return ;
+ case FileInputStatus.ERROR:
+ return ;
}
}
}
\ No newline at end of file
diff --git a/src/renderer/components/icon/icon.tsx b/src/renderer/components/icon/icon.tsx
index 24ff28b7c1..bc7534d167 100644
--- a/src/renderer/components/icon/icon.tsx
+++ b/src/renderer/components/icon/icon.tsx
@@ -48,12 +48,12 @@ export class Icon extends React.PureComponent {
@autobind()
onKeyDown(evt: React.KeyboardEvent) {
switch (evt.nativeEvent.code) {
- case "Space":
- case "Enter":
- const icon = findDOMNode(this) as HTMLElement;
- setTimeout(() => icon.click());
- evt.preventDefault();
- break;
+ case "Space":
+ case "Enter":
+ const icon = findDOMNode(this) as HTMLElement;
+ setTimeout(() => icon.click());
+ evt.preventDefault();
+ break;
}
if (this.props.onKeyDown) {
this.props.onKeyDown(evt);
diff --git a/src/renderer/components/input/input.tsx b/src/renderer/components/input/input.tsx
index 6b4667af83..6da3df2bd0 100644
--- a/src/renderer/components/input/input.tsx
+++ b/src/renderer/components/input/input.tsx
@@ -224,11 +224,11 @@ export class Input extends React.Component {
}
switch (evt.key) {
- case "Enter":
- if (this.props.onSubmit && !modified && !evt.repeat) {
- this.props.onSubmit(this.getValue());
- }
- break;
+ case "Enter":
+ if (this.props.onSubmit && !modified && !evt.repeat) {
+ this.props.onSubmit(this.getValue());
+ }
+ break;
}
}
diff --git a/src/renderer/components/item-object-list/filter-icon.tsx b/src/renderer/components/item-object-list/filter-icon.tsx
index 801c9116be..80d7e0d473 100644
--- a/src/renderer/components/item-object-list/filter-icon.tsx
+++ b/src/renderer/components/item-object-list/filter-icon.tsx
@@ -9,13 +9,13 @@ interface Props extends Partial {
export function FilterIcon(props: Props) {
const { type, ...iconProps } = props;
switch (type) {
- case FilterType.NAMESPACE:
- return ;
+ case FilterType.NAMESPACE:
+ return ;
- case FilterType.SEARCH:
- return ;
+ case FilterType.SEARCH:
+ return ;
- default:
- return ;
+ default:
+ return ;
}
}
diff --git a/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx b/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx
index a2393824ef..6f4a4d2007 100644
--- a/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx
+++ b/src/renderer/components/kube-object-status-icon/kube-object-status-icon.tsx
@@ -21,27 +21,27 @@ export class KubeObjectStatusIcon extends React.Component {
statusClassName(level: number): string {
switch (level) {
- case KubeObjectStatusLevel.INFO:
- return "info";
- case KubeObjectStatusLevel.WARNING:
- return "warning";
- case KubeObjectStatusLevel.CRITICAL:
- return "error";
- default:
- return "";
+ case KubeObjectStatusLevel.INFO:
+ return "info";
+ case KubeObjectStatusLevel.WARNING:
+ return "warning";
+ case KubeObjectStatusLevel.CRITICAL:
+ return "error";
+ default:
+ return "";
}
}
statusTitle(level: number): string {
switch (level) {
- case KubeObjectStatusLevel.INFO:
- return "Info";
- case KubeObjectStatusLevel.WARNING:
- return "Warning";
- case KubeObjectStatusLevel.CRITICAL:
- return "Critical";
- default:
- return "";
+ case KubeObjectStatusLevel.INFO:
+ return "Info";
+ case KubeObjectStatusLevel.WARNING:
+ return "Warning";
+ case KubeObjectStatusLevel.CRITICAL:
+ return "Critical";
+ default:
+ return "";
}
}
diff --git a/src/renderer/components/layout/sidebar.tsx b/src/renderer/components/layout/sidebar.tsx
index 428794764f..0c56923c28 100644
--- a/src/renderer/components/layout/sidebar.tsx
+++ b/src/renderer/components/layout/sidebar.tsx
@@ -29,7 +29,7 @@ import { CustomResources } from "../+custom-resources/custom-resources";
import { isActiveRoute, navigation } from "../../navigation";
import { isAllowedResource } from "../../../common/rbac";
import { Spinner } from "../spinner";
-import { clusterPageMenuRegistry, clusterPageRegistry, getExtensionPageUrl } from "../../../extensions/registries";
+import { ClusterPageMenuRegistration, clusterPageMenuRegistry, clusterPageRegistry, getExtensionPageUrl, RegisteredPage } from "../../../extensions/registries";
const SidebarContext = React.createContext({ pinned: false });
type SidebarContextValue = {
@@ -76,6 +76,52 @@ export class Sidebar extends React.Component {
});
}
+ getTabLayoutRoutes(menu: ClusterPageMenuRegistration): TabLayoutRoute[] {
+ if (!menu.id) {
+ return [];
+ }
+ const routes: TabLayoutRoute[] = [];
+
+ clusterPageMenuRegistry.getSubItems(menu).forEach((subItem) => {
+ const subPage = clusterPageRegistry.getByPageMenuTarget(subItem.target);
+ if (subPage) {
+ routes.push({
+ routePath: subPage.routePath,
+ url: getExtensionPageUrl({ extensionId: subPage.extensionId, pageId: subPage.id, params: subItem.target.params }),
+ title: subItem.title,
+ component: subPage.components.Page,
+ exact: subPage.exact
+ });
+ }
+ });
+ return routes;
+ }
+
+ renderRegisteredMenus() {
+ return clusterPageMenuRegistry.getRootItems().map((menuItem) => {
+ const registeredPage = clusterPageRegistry.getByPageMenuTarget(menuItem.target);
+ let pageUrl: string;
+ let isActive = false;
+ if (registeredPage) {
+ const { extensionId, id: pageId } = registeredPage;
+ pageUrl = getExtensionPageUrl({ extensionId, pageId, params: menuItem.target.params });
+ isActive = pageUrl === navigation.location.pathname;
+ }
+ const tabRoutes = this.getTabLayoutRoutes(menuItem);
+ if (!registeredPage && tabRoutes.length == 0) {
+ return;
+ }
+ return (
+ }
+ isActive={isActive}
+ subMenus={tabRoutes}
+ />
+ );
+ });
+ }
+
render() {
const { toggle, isPinned, className } = this.props;
const query = namespaceStore.getContextParams();
@@ -191,20 +237,7 @@ export class Sidebar extends React.Component {
>
{this.renderCustomResources()}
- {clusterPageMenuRegistry.getItems().map(({ title, target, components: { Icon } }) => {
- const registeredPage = clusterPageRegistry.getByPageMenuTarget(target);
- if (!registeredPage) return;
- const { extensionId, id: pageId } = registeredPage;
- const pageUrl = getExtensionPageUrl({ extensionId, pageId, params: target.params });
- const isActive = pageUrl === navigation.location.pathname;
- return (
- }
- isActive={isActive}
- />
- );
- })}
+ {this.renderRegisteredMenus()}
diff --git a/src/renderer/components/menu/menu.tsx b/src/renderer/components/menu/menu.tsx
index 8456a5e180..f9869726c7 100644
--- a/src/renderer/components/menu/menu.tsx
+++ b/src/renderer/components/menu/menu.tsx
@@ -166,25 +166,25 @@ export class Menu extends React.Component {
onKeyDown(evt: KeyboardEvent) {
if (!this.isOpen) return;
switch (evt.code) {
- case "Escape":
- this.close();
- break;
+ case "Escape":
+ this.close();
+ break;
- case "Space":
- case "Enter":
- const focusedItem = this.focusedItem;
- if (focusedItem) {
- focusedItem.elem.click();
- evt.preventDefault();
- }
- break;
+ case "Space":
+ case "Enter":
+ const focusedItem = this.focusedItem;
+ if (focusedItem) {
+ focusedItem.elem.click();
+ evt.preventDefault();
+ }
+ break;
- case "ArrowUp":
- this.focusNextItem(true);
- break;
- case "ArrowDown":
- this.focusNextItem();
- break;
+ case "ArrowUp":
+ this.focusNextItem(true);
+ break;
+ case "ArrowDown":
+ this.focusNextItem();
+ break;
}
}
diff --git a/src/renderer/components/tooltip/tooltip.tsx b/src/renderer/components/tooltip/tooltip.tsx
index 3d0ac4d196..8ae746e1cb 100644
--- a/src/renderer/components/tooltip/tooltip.tsx
+++ b/src/renderer/components/tooltip/tooltip.tsx
@@ -146,38 +146,38 @@ export class Tooltip extends React.Component {
const topCenter = targetBounds.top - tooltipBounds.height - offset;
const bottomCenter = targetBounds.bottom + offset;
switch (position) {
- case "top":
- left = horizontalCenter;
- top = topCenter;
- break;
- case "bottom":
- left = horizontalCenter;
- top = bottomCenter;
- break;
- case "left":
- top = verticalCenter;
- left = targetBounds.left - tooltipBounds.width - offset;
- break;
- case "right":
- top = verticalCenter;
- left = targetBounds.right + offset;
- break;
- case "top_left":
- left = targetBounds.left;
- top = topCenter;
- break;
- case "top_right":
- left = targetBounds.right - tooltipBounds.width;
- top = topCenter;
- break;
- case "bottom_left":
- top = bottomCenter;
- left = targetBounds.left;
- break;
- case "bottom_right":
- top = bottomCenter;
- left = targetBounds.right - tooltipBounds.width;
- break;
+ case "top":
+ left = horizontalCenter;
+ top = topCenter;
+ break;
+ case "bottom":
+ left = horizontalCenter;
+ top = bottomCenter;
+ break;
+ case "left":
+ top = verticalCenter;
+ left = targetBounds.left - tooltipBounds.width - offset;
+ break;
+ case "right":
+ top = verticalCenter;
+ left = targetBounds.right + offset;
+ break;
+ case "top_left":
+ left = targetBounds.left;
+ top = topCenter;
+ break;
+ case "top_right":
+ left = targetBounds.right - tooltipBounds.width;
+ top = topCenter;
+ break;
+ case "bottom_left":
+ top = bottomCenter;
+ left = targetBounds.left;
+ break;
+ case "bottom_right":
+ top = bottomCenter;
+ left = targetBounds.right - tooltipBounds.width;
+ break;
}
return {
left: left,
diff --git a/src/renderer/kube-object.store.ts b/src/renderer/kube-object.store.ts
index 7803ed2912..1a6d0e5470 100644
--- a/src/renderer/kube-object.store.ts
+++ b/src/renderer/kube-object.store.ts
@@ -174,20 +174,20 @@ export abstract class KubeObjectStore extends ItemSt
const api = apiManager.getApi(selfLink);
switch (type) {
- case "ADDED":
- case "MODIFIED":
- const newItem = new api.objectConstructor(object);
- if (!item) {
- items.push(newItem);
- } else {
- items.splice(index, 1, newItem);
- }
- break;
- case "DELETED":
- if (item) {
- items.splice(index, 1);
- }
- break;
+ case "ADDED":
+ case "MODIFIED":
+ const newItem = new api.objectConstructor(object);
+ if (!item) {
+ items.push(newItem);
+ } else {
+ items.splice(index, 1, newItem);
+ }
+ break;
+ case "DELETED":
+ if (item) {
+ items.splice(index, 1);
+ }
+ break;
}
});