diff --git a/package.json b/package.json index f108fc5662..0a1d5c4021 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "dev": "concurrently -i -k \"yarn run dev-run -C\" yarn:dev:*", "dev-build": "concurrently yarn:compile:*", "debug-build": "concurrently yarn:compile:main yarn:compile:extension-types", - "dev-run": "nodemon --watch static/build/main.js --exec \"electron --remote-debugging-port=9223 --inspect .\"", + "dev-run": "nodemon --watch static/build/main.js --exec \"electron --remote-debugging-port=9223 --inspect=9229 .\"", "dev:main": "yarn run compile:main --watch", "dev:renderer": "yarn run webpack-dev-server --config webpack.renderer.ts", "dev:extension-types": "yarn run compile:extension-types --watch", @@ -196,7 +196,6 @@ "chokidar": "^3.4.3", "command-exists": "1.2.9", "conf": "^7.0.1", - "cross-fetch": "^3.1.4", "crypto-js": "^4.0.0", "electron-devtools-installer": "^3.2.0", "electron-updater": "^4.3.1", @@ -222,6 +221,7 @@ "mock-fs": "^4.14.0", "moment": "^2.29.1", "moment-timezone": "^0.5.33", + "node-fetch": "^2.6.1", "node-pty": "^0.10.1", "npm": "^6.14.8", "openid-client": "^3.15.2", @@ -284,6 +284,7 @@ "@types/mock-fs": "^4.13.1", "@types/module-alias": "^2.0.0", "@types/node": "12.20", + "@types/node-fetch": "^2.5.12", "@types/npm": "^2.0.31", "@types/progress-bar-webpack-plugin": "^2.1.2", "@types/proper-lockfile": "^4.1.1", diff --git a/src/common/k8s-api/api-manager.ts b/src/common/k8s-api/api-manager.ts index 8eabef621a..3070f932be 100644 --- a/src/common/k8s-api/api-manager.ts +++ b/src/common/k8s-api/api-manager.ts @@ -49,6 +49,8 @@ export class ApiManager { } registerApi(apiBase: string, api: KubeApi) { + if (!api.apiBase) return; + if (!this.apis.has(apiBase)) { this.stores.forEach((store) => { if (store.api === api) { @@ -84,8 +86,8 @@ export class ApiManager { @action registerStore(store: KubeObjectStore, apis: KubeApi[] = [store.api]) { - apis.forEach(api => { - this.stores.set(api.apiBase, store); + apis.filter(Boolean).forEach(api => { + if (api.apiBase) this.stores.set(api.apiBase, store); }); } diff --git a/src/common/k8s-api/endpoints/cluster-role-binding.api.ts b/src/common/k8s-api/endpoints/cluster-role-binding.api.ts index 868f00261a..ffee9cc11c 100644 --- a/src/common/k8s-api/endpoints/cluster-role-binding.api.ts +++ b/src/common/k8s-api/endpoints/cluster-role-binding.api.ts @@ -18,6 +18,7 @@ * 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 { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; import { KubeApi } from "../kube-api"; import { KubeObject } from "../kube-object"; @@ -53,6 +54,17 @@ export class ClusterRoleBinding extends KubeObject { } } -export const clusterRoleBindingApi = new KubeApi({ - objectConstructor: ClusterRoleBinding, -}); +/** + * Only available within kubernetes cluster pages + */ +let clusterRoleBindingApi: KubeApi; + +if (isClusterPageContext()) { + clusterRoleBindingApi = new KubeApi({ + objectConstructor: ClusterRoleBinding, + }); +} + +export { + clusterRoleBindingApi +}; diff --git a/src/common/k8s-api/endpoints/cluster-role.api.ts b/src/common/k8s-api/endpoints/cluster-role.api.ts index 55a2f5283d..5b8dc78efb 100644 --- a/src/common/k8s-api/endpoints/cluster-role.api.ts +++ b/src/common/k8s-api/endpoints/cluster-role.api.ts @@ -19,6 +19,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; import { KubeApi } from "../kube-api"; import { KubeObject } from "../kube-object"; @@ -41,6 +42,17 @@ export class ClusterRole extends KubeObject { } } -export const clusterRoleApi = new KubeApi({ - objectConstructor: ClusterRole, -}); +/** + * Only available within kubernetes cluster pages + */ +let clusterRoleApi: KubeApi; + +if (isClusterPageContext()) { // initialize automatically only when within a cluster iframe/context + clusterRoleApi = new KubeApi({ + objectConstructor: ClusterRole, + }); +} + +export { + clusterRoleApi +}; diff --git a/src/common/k8s-api/endpoints/cluster.api.ts b/src/common/k8s-api/endpoints/cluster.api.ts index f0879fa501..420736b8e5 100644 --- a/src/common/k8s-api/endpoints/cluster.api.ts +++ b/src/common/k8s-api/endpoints/cluster.api.ts @@ -22,6 +22,7 @@ import { IMetrics, IMetricsReqParams, metricsApi } from "./metrics.api"; import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class ClusterApi extends KubeApi { static kind = "Cluster"; @@ -122,6 +123,17 @@ export class Cluster extends KubeObject { } } -export const clusterApi = new ClusterApi({ - objectConstructor: Cluster, -}); +/** + * Only available within kubernetes cluster pages + */ +let clusterApi: ClusterApi; + +if (isClusterPageContext()) { // initialize automatically only when within a cluster iframe/context + clusterApi = new ClusterApi({ + objectConstructor: Cluster, + }); +} + +export { + clusterApi +}; diff --git a/src/common/k8s-api/endpoints/configmap.api.ts b/src/common/k8s-api/endpoints/configmap.api.ts index 95a69f945e..d82ef6f926 100644 --- a/src/common/k8s-api/endpoints/configmap.api.ts +++ b/src/common/k8s-api/endpoints/configmap.api.ts @@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object"; import type { KubeJsonApiData } from "../kube-json-api"; import { KubeApi } from "../kube-api"; import { autoBind } from "../../utils"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface ConfigMap { data: { @@ -47,6 +48,17 @@ export class ConfigMap extends KubeObject { } } -export const configMapApi = new KubeApi({ - objectConstructor: ConfigMap, -}); +/** + * Only available within kubernetes cluster pages + */ +let configMapApi: KubeApi; + +if (isClusterPageContext()) { + configMapApi = new KubeApi({ + objectConstructor: ConfigMap, + }); +} + +export { + configMapApi +}; diff --git a/src/common/k8s-api/endpoints/crd.api.ts b/src/common/k8s-api/endpoints/crd.api.ts index c0989cb139..6729aaa46d 100644 --- a/src/common/k8s-api/endpoints/crd.api.ts +++ b/src/common/k8s-api/endpoints/crd.api.ts @@ -22,6 +22,7 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; import { crdResourcesURL } from "../../routes"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; type AdditionalPrinterColumnsCommon = { name: string; @@ -174,7 +175,18 @@ export class CustomResourceDefinition extends KubeObject { } } -export const crdApi = new KubeApi({ - objectConstructor: CustomResourceDefinition, - checkPreferredVersion: true, -}); +/** + * Only available within kubernetes cluster pages + */ +let crdApi: KubeApi; + +if (isClusterPageContext()) { + crdApi = new KubeApi({ + objectConstructor: CustomResourceDefinition, + checkPreferredVersion: true, + }); +} + +export { + crdApi +}; diff --git a/src/common/k8s-api/endpoints/cron-job.api.ts b/src/common/k8s-api/endpoints/cron-job.api.ts index 43743b2bb4..325da02a57 100644 --- a/src/common/k8s-api/endpoints/cron-job.api.ts +++ b/src/common/k8s-api/endpoints/cron-job.api.ts @@ -26,6 +26,7 @@ import { formatDuration } from "../../utils/formatDuration"; import { autoBind } from "../../utils"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class CronJobApi extends KubeApi { suspend(params: { namespace: string; name: string }) { @@ -140,6 +141,17 @@ export class CronJob extends KubeObject { } } -export const cronJobApi = new CronJobApi({ - objectConstructor: CronJob, -}); +/** + * Only available within kubernetes cluster pages + */ +let cronJobApi: CronJobApi; + +if (isClusterPageContext()) { + cronJobApi = new CronJobApi({ + objectConstructor: CronJob, + }); +} + +export { + cronJobApi +}; diff --git a/src/common/k8s-api/endpoints/daemon-set.api.ts b/src/common/k8s-api/endpoints/daemon-set.api.ts index cb584806d4..84e0967ce0 100644 --- a/src/common/k8s-api/endpoints/daemon-set.api.ts +++ b/src/common/k8s-api/endpoints/daemon-set.api.ts @@ -26,6 +26,7 @@ import { KubeApi } from "../kube-api"; import { metricsApi } from "./metrics.api"; import type { KubeJsonApiData } from "../kube-json-api"; import type { IPodContainer, IPodMetrics } from "./pods.api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class DaemonSet extends WorkloadKubeObject { static kind = "DaemonSet"; @@ -116,6 +117,17 @@ export function getMetricsForDaemonSets(daemonsets: DaemonSet[], namespace: stri }); } -export const daemonSetApi = new DaemonSetApi({ - objectConstructor: DaemonSet, -}); +/** + * Only available within kubernetes cluster pages + */ +let daemonSetApi: DaemonSetApi; + +if (isClusterPageContext()) { + daemonSetApi = new DaemonSetApi({ + objectConstructor: DaemonSet, + }); +} + +export { + daemonSetApi +}; diff --git a/src/common/k8s-api/endpoints/deployment.api.ts b/src/common/k8s-api/endpoints/deployment.api.ts index 0d5bef48dd..f8a2b401ae 100644 --- a/src/common/k8s-api/endpoints/deployment.api.ts +++ b/src/common/k8s-api/endpoints/deployment.api.ts @@ -27,6 +27,7 @@ import { KubeApi } from "../kube-api"; import { metricsApi } from "./metrics.api"; import type { IPodMetrics } from "./pods.api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class DeploymentApi extends KubeApi { protected getScaleApiUrl(params: { namespace: string; name: string }) { @@ -232,6 +233,14 @@ export class Deployment extends WorkloadKubeObject { } } -export const deploymentApi = new DeploymentApi({ - objectConstructor: Deployment, -}); +let deploymentApi: DeploymentApi; + +if (isClusterPageContext()) { + deploymentApi = new DeploymentApi({ + objectConstructor: Deployment, + }); +} + +export { + deploymentApi +}; diff --git a/src/common/k8s-api/endpoints/endpoint.api.ts b/src/common/k8s-api/endpoints/endpoint.api.ts index 14bc399062..48296908d9 100644 --- a/src/common/k8s-api/endpoints/endpoint.api.ts +++ b/src/common/k8s-api/endpoints/endpoint.api.ts @@ -24,6 +24,7 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; import { get } from "lodash"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface IEndpointPort { name?: string; @@ -149,6 +150,14 @@ export class Endpoint extends KubeObject { } -export const endpointApi = new KubeApi({ - objectConstructor: Endpoint, -}); +let endpointApi: KubeApi; + +if (isClusterPageContext()) { + endpointApi = new KubeApi({ + objectConstructor: Endpoint, + }); +} + +export { + endpointApi +}; diff --git a/src/common/k8s-api/endpoints/events.api.ts b/src/common/k8s-api/endpoints/events.api.ts index ad194a532a..ee1695184e 100644 --- a/src/common/k8s-api/endpoints/events.api.ts +++ b/src/common/k8s-api/endpoints/events.api.ts @@ -23,6 +23,7 @@ import moment from "moment"; import { KubeObject } from "../kube-object"; import { formatDuration } from "../../utils/formatDuration"; import { KubeApi } from "../kube-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface KubeEvent { involvedObject: { @@ -77,6 +78,14 @@ export class KubeEvent extends KubeObject { } } -export const eventApi = new KubeApi({ - objectConstructor: KubeEvent, -}); +let eventApi: KubeApi; + +if (isClusterPageContext()) { + eventApi = new KubeApi({ + objectConstructor: KubeEvent, + }); +} + +export { + eventApi +}; diff --git a/src/common/k8s-api/endpoints/helm-charts.api.ts b/src/common/k8s-api/endpoints/helm-charts.api.ts index 2244bca1f2..c7bc662b75 100644 --- a/src/common/k8s-api/endpoints/helm-charts.api.ts +++ b/src/common/k8s-api/endpoints/helm-charts.api.ts @@ -23,6 +23,7 @@ import { compile } from "path-to-regexp"; import { apiBase } from "../index"; import { stringify } from "querystring"; import { autoBind } from "../../utils"; +import type { RequestInit } from "node-fetch"; export type RepoHelmChartList = Record; export type HelmChartList = Record; diff --git a/src/common/k8s-api/endpoints/hpa.api.ts b/src/common/k8s-api/endpoints/hpa.api.ts index dba89d4111..33ad5735ab 100644 --- a/src/common/k8s-api/endpoints/hpa.api.ts +++ b/src/common/k8s-api/endpoints/hpa.api.ts @@ -21,6 +21,7 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export enum HpaMetricType { Resource = "Resource", @@ -163,6 +164,14 @@ export class HorizontalPodAutoscaler extends KubeObject { } } -export const hpaApi = new KubeApi({ - objectConstructor: HorizontalPodAutoscaler, -}); +let hpaApi: KubeApi; + +if (isClusterPageContext()) { + hpaApi = new KubeApi({ + objectConstructor: HorizontalPodAutoscaler, + }); +} + +export { + hpaApi +}; diff --git a/src/common/k8s-api/endpoints/ingress.api.ts b/src/common/k8s-api/endpoints/ingress.api.ts index 31745f30c4..99aeb59124 100644 --- a/src/common/k8s-api/endpoints/ingress.api.ts +++ b/src/common/k8s-api/endpoints/ingress.api.ts @@ -24,6 +24,7 @@ import { autoBind } from "../../utils"; import { IMetrics, metricsApi } from "./metrics.api"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class IngressApi extends KubeApi { } @@ -203,10 +204,17 @@ export class Ingress extends KubeObject { } } -export const ingressApi = new IngressApi({ - objectConstructor: Ingress, - // Add fallback for Kubernetes <1.19 - checkPreferredVersion: true, - fallbackApiBases: ["/apis/extensions/v1beta1/ingresses"], - logStuff: true -} as any); +let ingressApi: IngressApi; + +if (isClusterPageContext()) { + ingressApi = new IngressApi({ + objectConstructor: Ingress, + // Add fallback for Kubernetes <1.19 + checkPreferredVersion: true, + fallbackApiBases: ["/apis/extensions/v1beta1/ingresses"], + }); +} + +export { + ingressApi +}; diff --git a/src/common/k8s-api/endpoints/job.api.ts b/src/common/k8s-api/endpoints/job.api.ts index 823a04bef9..186b2e0397 100644 --- a/src/common/k8s-api/endpoints/job.api.ts +++ b/src/common/k8s-api/endpoints/job.api.ts @@ -27,6 +27,7 @@ import { metricsApi } from "./metrics.api"; import type { JsonApiParams } from "../json-api"; import type { KubeJsonApiData } from "../kube-json-api"; import type { IPodContainer, IPodMetrics } from "./pods.api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class Job extends WorkloadKubeObject { static kind = "Job"; @@ -148,6 +149,14 @@ export function getMetricsForJobs(jobs: Job[], namespace: string, selector = "") }); } -export const jobApi = new JobApi({ - objectConstructor: Job, -}); +let jobApi: JobApi; + +if (isClusterPageContext()) { + jobApi = new JobApi({ + objectConstructor: Job, + }); +} + +export { + jobApi +}; diff --git a/src/common/k8s-api/endpoints/limit-range.api.ts b/src/common/k8s-api/endpoints/limit-range.api.ts index 82b02cfa70..bddef5aeaf 100644 --- a/src/common/k8s-api/endpoints/limit-range.api.ts +++ b/src/common/k8s-api/endpoints/limit-range.api.ts @@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; import { autoBind } from "../../utils"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export enum LimitType { CONTAINER = "Container", @@ -80,6 +81,14 @@ export class LimitRange extends KubeObject { } } -export const limitRangeApi = new KubeApi({ - objectConstructor: LimitRange, -}); +let limitRangeApi: KubeApi; + +if (isClusterPageContext()) { + limitRangeApi = new KubeApi({ + objectConstructor: LimitRange, + }); +} + +export { + limitRangeApi +}; diff --git a/src/common/k8s-api/endpoints/namespaces.api.ts b/src/common/k8s-api/endpoints/namespaces.api.ts index 7e9d6fa9a4..8b1f897b9a 100644 --- a/src/common/k8s-api/endpoints/namespaces.api.ts +++ b/src/common/k8s-api/endpoints/namespaces.api.ts @@ -25,6 +25,7 @@ import { autoBind } from "../../../renderer/utils"; import { metricsApi } from "./metrics.api"; import type { IPodMetrics } from "./pods.api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export enum NamespaceStatus { ACTIVE = "Active", @@ -69,6 +70,14 @@ export function getMetricsForNamespace(namespace: string, selector = ""): Promis }); } -export const namespacesApi = new NamespaceApi({ - objectConstructor: Namespace, -}); +let namespacesApi: NamespaceApi; + +if (isClusterPageContext()) { + namespacesApi = new NamespaceApi({ + objectConstructor: Namespace, + }); +} + +export { + namespacesApi +}; diff --git a/src/common/k8s-api/endpoints/network-policy.api.ts b/src/common/k8s-api/endpoints/network-policy.api.ts index 03a06b7c42..fc92c9c91d 100644 --- a/src/common/k8s-api/endpoints/network-policy.api.ts +++ b/src/common/k8s-api/endpoints/network-policy.api.ts @@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object"; import { autoBind } from "../../utils"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface IPolicyIpBlock { cidr: string; @@ -96,6 +97,14 @@ export class NetworkPolicy extends KubeObject { } } -export const networkPolicyApi = new KubeApi({ - objectConstructor: NetworkPolicy, -}); +let networkPolicyApi: KubeApi; + +if (isClusterPageContext()) { + networkPolicyApi = new KubeApi({ + objectConstructor: NetworkPolicy, + }); +} + +export { + networkPolicyApi +}; diff --git a/src/common/k8s-api/endpoints/nodes.api.ts b/src/common/k8s-api/endpoints/nodes.api.ts index d03c5f96d9..d578a5a825 100644 --- a/src/common/k8s-api/endpoints/nodes.api.ts +++ b/src/common/k8s-api/endpoints/nodes.api.ts @@ -24,6 +24,7 @@ import { autoBind, cpuUnitsToNumber, unitsToBytes } from "../../../renderer/util import { IMetrics, metricsApi } from "./metrics.api"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class NodesApi extends KubeApi { } @@ -225,6 +226,14 @@ export class Node extends KubeObject { } } -export const nodesApi = new NodesApi({ - objectConstructor: Node, -}); +let nodesApi: NodesApi; + +if (isClusterPageContext()) { + nodesApi = new NodesApi({ + objectConstructor: Node, + }); +} + +export { + nodesApi +}; diff --git a/src/common/k8s-api/endpoints/persistent-volume-claims.api.ts b/src/common/k8s-api/endpoints/persistent-volume-claims.api.ts index 356122569a..ab09d70e8d 100644 --- a/src/common/k8s-api/endpoints/persistent-volume-claims.api.ts +++ b/src/common/k8s-api/endpoints/persistent-volume-claims.api.ts @@ -25,6 +25,7 @@ import { IMetrics, metricsApi } from "./metrics.api"; import type { Pod } from "./pods.api"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class PersistentVolumeClaimsApi extends KubeApi { } @@ -116,6 +117,14 @@ export class PersistentVolumeClaim extends KubeObject { } } -export const pvcApi = new PersistentVolumeClaimsApi({ - objectConstructor: PersistentVolumeClaim, -}); +let pvcApi: PersistentVolumeClaimsApi; + +if (isClusterPageContext()) { + pvcApi = new PersistentVolumeClaimsApi({ + objectConstructor: PersistentVolumeClaim, + }); +} + +export { + pvcApi +}; diff --git a/src/common/k8s-api/endpoints/persistent-volume.api.ts b/src/common/k8s-api/endpoints/persistent-volume.api.ts index 76c2563af0..4095171ea7 100644 --- a/src/common/k8s-api/endpoints/persistent-volume.api.ts +++ b/src/common/k8s-api/endpoints/persistent-volume.api.ts @@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object"; import { autoBind, unitsToBytes } from "../../utils"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface PersistentVolume { spec: { @@ -101,6 +102,14 @@ export class PersistentVolume extends KubeObject { } } -export const persistentVolumeApi = new KubeApi({ - objectConstructor: PersistentVolume, -}); +let persistentVolumeApi: KubeApi; + +if (isClusterPageContext()) { + persistentVolumeApi = new KubeApi({ + objectConstructor: PersistentVolume, + }); +} + +export { + persistentVolumeApi +}; diff --git a/src/common/k8s-api/endpoints/pod-metrics.api.ts b/src/common/k8s-api/endpoints/pod-metrics.api.ts index 191a128267..cee259052e 100644 --- a/src/common/k8s-api/endpoints/pod-metrics.api.ts +++ b/src/common/k8s-api/endpoints/pod-metrics.api.ts @@ -21,6 +21,7 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface PodMetrics { timestamp: string; @@ -40,6 +41,14 @@ export class PodMetrics extends KubeObject { static apiBase = "/apis/metrics.k8s.io/v1beta1/pods"; } -export const podMetricsApi = new KubeApi({ - objectConstructor: PodMetrics, -}); +let podMetricsApi: KubeApi; + +if (isClusterPageContext()) { + podMetricsApi = new KubeApi({ + objectConstructor: PodMetrics, + }); +} + +export { + podMetricsApi +}; diff --git a/src/common/k8s-api/endpoints/poddisruptionbudget.api.ts b/src/common/k8s-api/endpoints/poddisruptionbudget.api.ts index daa16933da..4cfeef5070 100644 --- a/src/common/k8s-api/endpoints/poddisruptionbudget.api.ts +++ b/src/common/k8s-api/endpoints/poddisruptionbudget.api.ts @@ -23,6 +23,7 @@ import { autoBind } from "../../utils"; import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface PodDisruptionBudget { spec: { @@ -72,6 +73,14 @@ export class PodDisruptionBudget extends KubeObject { } -export const pdbApi = new KubeApi({ - objectConstructor: PodDisruptionBudget, -}); +let pdbApi: KubeApi; + +if (isClusterPageContext()) { + pdbApi = new KubeApi({ + objectConstructor: PodDisruptionBudget, + }); +} + +export { + pdbApi +}; diff --git a/src/common/k8s-api/endpoints/pods.api.ts b/src/common/k8s-api/endpoints/pods.api.ts index e4d33c75bc..bcafdafc64 100644 --- a/src/common/k8s-api/endpoints/pods.api.ts +++ b/src/common/k8s-api/endpoints/pods.api.ts @@ -24,6 +24,7 @@ import { autoBind } from "../../utils"; import { IMetrics, metricsApi } from "./metrics.api"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class PodsApi extends KubeApi { async getLogs(params: { namespace: string; name: string }, query?: IPodLogsQuery): Promise { @@ -502,6 +503,14 @@ export class Pod extends WorkloadKubeObject { } } -export const podsApi = new PodsApi({ - objectConstructor: Pod, -}); +let podsApi: PodsApi; + +if (isClusterPageContext()) { + podsApi = new PodsApi({ + objectConstructor: Pod, + }); +} + +export { + podsApi +}; diff --git a/src/common/k8s-api/endpoints/podsecuritypolicy.api.ts b/src/common/k8s-api/endpoints/podsecuritypolicy.api.ts index eac827ffcc..19ed59f5ca 100644 --- a/src/common/k8s-api/endpoints/podsecuritypolicy.api.ts +++ b/src/common/k8s-api/endpoints/podsecuritypolicy.api.ts @@ -23,6 +23,7 @@ import { autoBind } from "../../utils"; import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface PodSecurityPolicy { spec: { @@ -117,6 +118,14 @@ export class PodSecurityPolicy extends KubeObject { } } -export const pspApi = new KubeApi({ - objectConstructor: PodSecurityPolicy, -}); +let pspApi: KubeApi; + +if (isClusterPageContext()) { + pspApi = new KubeApi({ + objectConstructor: PodSecurityPolicy, + }); +} + +export { + pspApi +}; diff --git a/src/common/k8s-api/endpoints/replica-set.api.ts b/src/common/k8s-api/endpoints/replica-set.api.ts index 7e74d149c7..3e92209d5d 100644 --- a/src/common/k8s-api/endpoints/replica-set.api.ts +++ b/src/common/k8s-api/endpoints/replica-set.api.ts @@ -26,6 +26,7 @@ import { KubeApi } from "../kube-api"; import { metricsApi } from "./metrics.api"; import type { IPodContainer, IPodMetrics, Pod } from "./pods.api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class ReplicaSetApi extends KubeApi { protected getScaleApiUrl(params: { namespace: string; name: string }) { @@ -123,6 +124,14 @@ export class ReplicaSet extends WorkloadKubeObject { } } -export const replicaSetApi = new ReplicaSetApi({ - objectConstructor: ReplicaSet, -}); +let replicaSetApi: ReplicaSetApi; + +if (isClusterPageContext()) { + replicaSetApi = new ReplicaSetApi({ + objectConstructor: ReplicaSet, + }); +} + +export { + replicaSetApi +}; diff --git a/src/common/k8s-api/endpoints/resource-quota.api.ts b/src/common/k8s-api/endpoints/resource-quota.api.ts index 762c6682e1..6664e3eb6d 100644 --- a/src/common/k8s-api/endpoints/resource-quota.api.ts +++ b/src/common/k8s-api/endpoints/resource-quota.api.ts @@ -21,6 +21,7 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface IResourceQuotaValues { [quota: string]: string; @@ -80,6 +81,14 @@ export class ResourceQuota extends KubeObject { } } -export const resourceQuotaApi = new KubeApi({ - objectConstructor: ResourceQuota, -}); +let resourceQuotaApi: KubeApi; + +if (isClusterPageContext()) { + resourceQuotaApi = new KubeApi({ + objectConstructor: ResourceQuota, + }); +} + +export { + resourceQuotaApi +}; diff --git a/src/common/k8s-api/endpoints/role-binding.api.ts b/src/common/k8s-api/endpoints/role-binding.api.ts index c8c83d3151..73bf48d82a 100644 --- a/src/common/k8s-api/endpoints/role-binding.api.ts +++ b/src/common/k8s-api/endpoints/role-binding.api.ts @@ -23,6 +23,7 @@ import { autoBind } from "../../utils"; import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export type RoleBindingSubjectKind = "Group" | "ServiceAccount" | "User"; @@ -61,6 +62,14 @@ export class RoleBinding extends KubeObject { } } -export const roleBindingApi = new KubeApi({ - objectConstructor: RoleBinding, -}); +let roleBindingApi: KubeApi; + +if (isClusterPageContext()) { + roleBindingApi = new KubeApi({ + objectConstructor: RoleBinding, + }); +} + +export { + roleBindingApi +}; diff --git a/src/common/k8s-api/endpoints/role.api.ts b/src/common/k8s-api/endpoints/role.api.ts index b504c7fc8b..0be3bda9d1 100644 --- a/src/common/k8s-api/endpoints/role.api.ts +++ b/src/common/k8s-api/endpoints/role.api.ts @@ -21,6 +21,7 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface Role { rules: { @@ -41,6 +42,14 @@ export class Role extends KubeObject { } } -export const roleApi = new KubeApi({ - objectConstructor: Role, -}); +let roleApi: KubeApi; + +if (isClusterPageContext()) { + roleApi = new KubeApi({ + objectConstructor: Role, + }); +} + +export{ + roleApi +}; diff --git a/src/common/k8s-api/endpoints/secret.api.ts b/src/common/k8s-api/endpoints/secret.api.ts index 5ddd0e1db3..430a18e064 100644 --- a/src/common/k8s-api/endpoints/secret.api.ts +++ b/src/common/k8s-api/endpoints/secret.api.ts @@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object"; import type { KubeJsonApiData } from "../kube-json-api"; import { autoBind } from "../../utils"; import { KubeApi } from "../kube-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export enum SecretType { Opaque = "Opaque", @@ -69,6 +70,14 @@ export class Secret extends KubeObject { } } -export const secretsApi = new KubeApi({ - objectConstructor: Secret, -}); +let secretsApi: KubeApi; + +if (isClusterPageContext()) { + secretsApi = new KubeApi({ + objectConstructor: Secret, + }); +} + +export { + secretsApi +}; diff --git a/src/common/k8s-api/endpoints/selfsubjectrulesreviews.api.ts b/src/common/k8s-api/endpoints/selfsubjectrulesreviews.api.ts index 84c27f21cb..c40ba86909 100644 --- a/src/common/k8s-api/endpoints/selfsubjectrulesreviews.api.ts +++ b/src/common/k8s-api/endpoints/selfsubjectrulesreviews.api.ts @@ -21,6 +21,7 @@ import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class SelfSubjectRulesReviewApi extends KubeApi { create({ namespace = "default" }): Promise { @@ -86,6 +87,15 @@ export class SelfSubjectRulesReview extends KubeObject { } } -export const selfSubjectRulesReviewApi = new SelfSubjectRulesReviewApi({ - objectConstructor: SelfSubjectRulesReview, -}); +let selfSubjectRulesReviewApi: SelfSubjectRulesReviewApi; + +if (isClusterPageContext()) { + selfSubjectRulesReviewApi = new SelfSubjectRulesReviewApi({ + objectConstructor: SelfSubjectRulesReview, + }); +} + +export { + selfSubjectRulesReviewApi +}; + diff --git a/src/common/k8s-api/endpoints/service-accounts.api.ts b/src/common/k8s-api/endpoints/service-accounts.api.ts index 6cc9d292ba..67b3e1def0 100644 --- a/src/common/k8s-api/endpoints/service-accounts.api.ts +++ b/src/common/k8s-api/endpoints/service-accounts.api.ts @@ -23,6 +23,7 @@ import { autoBind } from "../../utils"; import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface ServiceAccount { secrets?: { @@ -52,6 +53,14 @@ export class ServiceAccount extends KubeObject { } } -export const serviceAccountsApi = new KubeApi({ - objectConstructor: ServiceAccount, -}); +let serviceAccountsApi: KubeApi; + +if (isClusterPageContext()) { + serviceAccountsApi = new KubeApi({ + objectConstructor: ServiceAccount, + }); +} + +export { + serviceAccountsApi +}; diff --git a/src/common/k8s-api/endpoints/service.api.ts b/src/common/k8s-api/endpoints/service.api.ts index d2c3d05684..c4f35db190 100644 --- a/src/common/k8s-api/endpoints/service.api.ts +++ b/src/common/k8s-api/endpoints/service.api.ts @@ -23,6 +23,7 @@ import { autoBind } from "../../../renderer/utils"; import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface ServicePort { name?: string; @@ -143,6 +144,14 @@ export class Service extends KubeObject { } } -export const serviceApi = new KubeApi({ - objectConstructor: Service, -}); +let serviceApi: KubeApi; + +if (isClusterPageContext()) { + serviceApi = new KubeApi({ + objectConstructor: Service, + }); +} + +export { + serviceApi +}; diff --git a/src/common/k8s-api/endpoints/stateful-set.api.ts b/src/common/k8s-api/endpoints/stateful-set.api.ts index 21f4c6e02e..cbf5e5a0e4 100644 --- a/src/common/k8s-api/endpoints/stateful-set.api.ts +++ b/src/common/k8s-api/endpoints/stateful-set.api.ts @@ -26,6 +26,7 @@ import { KubeApi } from "../kube-api"; import { metricsApi } from "./metrics.api"; import type { IPodContainer, IPodMetrics } from "./pods.api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export class StatefulSetApi extends KubeApi { protected getScaleApiUrl(params: { namespace: string; name: string }) { @@ -149,6 +150,14 @@ export class StatefulSet extends WorkloadKubeObject { } } -export const statefulSetApi = new StatefulSetApi({ - objectConstructor: StatefulSet, -}); +let statefulSetApi: StatefulSetApi; + +if (isClusterPageContext()) { + statefulSetApi = new StatefulSetApi({ + objectConstructor: StatefulSet, + }); +} + +export { + statefulSetApi +}; diff --git a/src/common/k8s-api/endpoints/storage-class.api.ts b/src/common/k8s-api/endpoints/storage-class.api.ts index 226e3ab477..7f35803b05 100644 --- a/src/common/k8s-api/endpoints/storage-class.api.ts +++ b/src/common/k8s-api/endpoints/storage-class.api.ts @@ -23,6 +23,7 @@ import { autoBind } from "../../utils"; import { KubeObject } from "../kube-object"; import { KubeApi } from "../kube-api"; import type { KubeJsonApiData } from "../kube-json-api"; +import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";; export interface StorageClass { provisioner: string; // e.g. "storage.k8s.io/v1" @@ -62,6 +63,14 @@ export class StorageClass extends KubeObject { } } -export const storageClassApi = new KubeApi({ - objectConstructor: StorageClass, -}); +let storageClassApi: KubeApi; + +if (isClusterPageContext()) { + storageClassApi = new KubeApi({ + objectConstructor: StorageClass, + }); +} + +export { + storageClassApi +}; diff --git a/src/common/k8s-api/index.ts b/src/common/k8s-api/index.ts index 8705b42da0..0c52098f6d 100644 --- a/src/common/k8s-api/index.ts +++ b/src/common/k8s-api/index.ts @@ -22,12 +22,34 @@ import { JsonApi } from "./json-api"; import { KubeJsonApi } from "./kube-json-api"; import { apiKubePrefix, apiPrefix, isDebugging, isDevelopment } from "../../common/vars"; +import { isClusterPageContext } from "../utils/cluster-id-url-parsing"; -export const apiBase = new JsonApi({ - apiBase: apiPrefix, - debug: isDevelopment || isDebugging, -}); -export const apiKube = new KubeJsonApi({ - apiBase: apiKubePrefix, - debug: isDevelopment, -}); +let apiBase: JsonApi; +let apiKube: KubeJsonApi; + +if (isClusterPageContext()) { + apiBase = new JsonApi({ + serverAddress: `http://127.0.0.1:${window.location.port}`, + apiBase: apiPrefix, + debug: isDevelopment || isDebugging, + }, { + headers: { + "Host": window.location.host + } + }); + + apiKube = new KubeJsonApi({ + serverAddress: `http://127.0.0.1:${window.location.port}`, + apiBase: apiKubePrefix, + debug: isDevelopment + }, { + headers: { + "Host": window.location.host + } + }); +} + +export { + apiBase, + apiKube +}; diff --git a/src/common/k8s-api/json-api.ts b/src/common/k8s-api/json-api.ts index 02a855050c..069963aa4e 100644 --- a/src/common/k8s-api/json-api.ts +++ b/src/common/k8s-api/json-api.ts @@ -21,11 +21,10 @@ // Base http-service / json-api class -import fetch from "cross-fetch"; +import { merge } from "lodash"; +import fetch, { Response, RequestInit } from "node-fetch"; import { stringify } from "querystring"; import { EventEmitter } from "../../common/event-emitter"; -import { randomBytes } from "crypto"; -import { ipcRenderer } from "electron"; import logger from "../../common/logger"; export interface JsonApiData { @@ -52,13 +51,14 @@ export interface JsonApiLog { export interface JsonApiConfig { apiBase: string; + serverAddress: string; debug?: boolean; } - export class JsonApi { static reqInitDefault: RequestInit = { headers: { - "content-type": "application/json" + "content-type": "application/json", + "connection": "keep-alive" } }; @@ -68,7 +68,7 @@ export class JsonApi { constructor(protected config: JsonApiConfig, protected reqInit?: RequestInit) { this.config = Object.assign({}, JsonApi.configDefault, config); - this.reqInit = Object.assign({}, JsonApi.reqInitDefault, reqInit); + this.reqInit = merge({}, JsonApi.reqInitDefault, reqInit); this.parseResponse = this.parseResponse.bind(this); } @@ -80,18 +80,8 @@ export class JsonApi { } getResponse(path: string, params?: P, init: RequestInit = {}): Promise { - const reqPath = `${this.config.apiBase}${path}`; - let reqUrl: string; - - if (ipcRenderer) { - const subdomain = randomBytes(2).toString("hex"); - - reqUrl = `http://${subdomain}.${window.location.host}${reqPath}`; // hack around browser connection limits (chromium allows 6 per domain) - } else { - reqUrl = reqPath; - } - - const reqInit: RequestInit = { ...init }; + let reqUrl = `${this.config.serverAddress}${this.config.apiBase}${path}`; + const reqInit: RequestInit = merge({}, this.reqInit, init); const { query } = params || {} as P; if (!reqInit.method) { @@ -106,7 +96,7 @@ export class JsonApi { this.writeLog({ method: reqInit.method.toUpperCase(), - reqUrl: reqPath, + reqUrl, reqInit, }); @@ -130,8 +120,8 @@ export class JsonApi { } protected async request(path: string, params?: P, init: RequestInit = {}) { - let reqUrl = this.config.apiBase + path; - const reqInit: RequestInit = { ...this.reqInit, ...init }; + let reqUrl = `${this.config.serverAddress}${this.config.apiBase}${path}`; + const reqInit: RequestInit = merge({}, this.reqInit, init); const { data, query } = params || {} as P; if (data && !reqInit.body) { @@ -205,11 +195,7 @@ export class JsonApi { protected writeLog(log: JsonApiLog) { if (!this.config.debug) return; const { method, reqUrl, ...params } = log; - // let textStyle = "font-weight: bold;"; - // if (params.data) textStyle += "background: green; color: white;"; - // if (params.error) textStyle += "background: red; color: white;"; - //console.log(`%c${method} ${reqUrl}`, textStyle, params); logger.info(`[JSON-API] request ${method} ${reqUrl}`, params); } } diff --git a/src/common/k8s-api/kube-api.ts b/src/common/k8s-api/kube-api.ts index ba4b201403..964cfc396f 100644 --- a/src/common/k8s-api/kube-api.ts +++ b/src/common/k8s-api/kube-api.ts @@ -31,9 +31,10 @@ import { createKubeApiURL, parseKubeApi } from "./kube-api-parse"; import { KubeObjectConstructor, KubeObject, KubeStatus } from "./kube-object"; import byline from "byline"; import type { IKubeWatchEvent } from "./kube-watch-api"; -import { ReadableWebToNodeStream } from "../utils/readableStream"; import { KubeJsonApi, KubeJsonApiData } from "./kube-json-api"; import { noop } from "../utils"; +import type { RequestInit } from "node-fetch"; +import AbortController from "abort-controller"; export interface IKubeApiOptions { /** @@ -96,11 +97,12 @@ export interface IKubeApiCluster { export function forCluster(cluster: IKubeApiCluster, kubeClass: KubeObjectConstructor): KubeApi { const request = new KubeJsonApi({ + serverAddress: `http://127.0.0.1:${process.env.LENS_PROXY_PORT}`, apiBase: apiKubePrefix, debug: isDevelopment, }, { headers: { - "X-Cluster-ID": cluster.metadata.uid + "Host": `${cluster.metadata.uid}.localhost:${process.env.LENS_PROXY_PORT}` } }); @@ -434,7 +436,7 @@ export class KubeApi { }); const watchUrl = this.getWatchUrl(namespace); - const responsePromise = this.request.getResponse(watchUrl, null, { signal }); + const responsePromise = this.request.getResponse(watchUrl, null, { signal, timeout: 600_000 }); responsePromise .then(response => { @@ -442,10 +444,8 @@ export class KubeApi { return callback(null, response); } - const nodeStream = new ReadableWebToNodeStream(response.body); - ["end", "close", "error"].forEach((eventName) => { - nodeStream.on(eventName, () => { + response.body.on(eventName, () => { if (errorReceived) return; // kubernetes errors should be handled in a callback clearTimeout(timedRetry); @@ -455,7 +455,7 @@ export class KubeApi { }); }); - byline(nodeStream).on("data", (line) => { + byline(response.body).on("data", (line) => { try { const event: IKubeWatchEvent = JSON.parse(line); @@ -473,7 +473,10 @@ export class KubeApi { }); }) .catch(error => { - if (typeof DOMException === "function" && error instanceof DOMException) return; // AbortController rejects, we can ignore it + if (error?.type === "aborted") return; // AbortController rejects, we can ignore it + + console.trace(); + console.error(error); callback(null, error); }); diff --git a/src/common/k8s-api/kube-json-api.ts b/src/common/k8s-api/kube-json-api.ts index 432c6f8370..2e6e892b21 100644 --- a/src/common/k8s-api/kube-json-api.ts +++ b/src/common/k8s-api/kube-json-api.ts @@ -20,6 +20,7 @@ */ import { JsonApi, JsonApiData, JsonApiError } from "./json-api"; +import type { Response } from "node-fetch"; export interface KubeJsonApiListMetadata { resourceVersion: string; diff --git a/src/common/k8s-api/kube-object.store.ts b/src/common/k8s-api/kube-object.store.ts index b65426b489..bc77d5d26a 100644 --- a/src/common/k8s-api/kube-object.store.ts +++ b/src/common/k8s-api/kube-object.store.ts @@ -30,6 +30,8 @@ import { apiManager } from "./api-manager"; import { ensureObjectSelfLink, IKubeApiQueryParams, KubeApi } from "./kube-api"; import { parseKubeApi } from "./kube-api-parse"; import type { KubeJsonApiData } from "./kube-json-api"; +import type { RequestInit } from "node-fetch"; +import AbortController from "abort-controller"; export interface KubeObjectStoreLoadingParams { namespaces: string[]; @@ -347,7 +349,7 @@ export abstract class KubeObjectStore extends ItemStore const { signal } = abortController; const callback = (data: IKubeWatchEvent, error: any) => { - if (!this.isLoaded || error instanceof DOMException) return; + if (!this.isLoaded || error?.type === "aborted") return; if (error instanceof Response) { if (error.status === 404 || error.status === 401) { diff --git a/src/common/utils/cluster-id-url-parsing.ts b/src/common/utils/cluster-id-url-parsing.ts index e9517dce1d..e692bc4595 100644 --- a/src/common/utils/cluster-id-url-parsing.ts +++ b/src/common/utils/cluster-id-url-parsing.ts @@ -48,3 +48,12 @@ export function getClusterFrameUrl(clusterId: ClusterId) { export function getHostedClusterId(): ClusterId | undefined { return getClusterIdFromHost(location.host); } + +/** + * Returns true only if code is running within a cluster iframe context + */ +export function isClusterPageContext(): boolean { + if (typeof window === "undefined") return false; + + return !!getClusterIdFromHost(window.location.host); +} diff --git a/src/common/vars.ts b/src/common/vars.ts index 0dea82cab6..dec81f313e 100644 --- a/src/common/vars.ts +++ b/src/common/vars.ts @@ -42,6 +42,7 @@ export const publicPath = "/build/" as string; // Webpack build paths export const contextDir = process.cwd(); export const buildDir = path.join(contextDir, "static", publicPath); +export const preloadEntrypoint = path.join(contextDir, "src/preload.ts"); export const mainDir = path.join(contextDir, "src/main"); export const rendererDir = path.join(contextDir, "src/renderer"); export const htmlTemplate = path.resolve(rendererDir, "template.html"); diff --git a/src/main/lens-proxy.ts b/src/main/lens-proxy.ts index fef1183f32..353ed935e7 100644 --- a/src/main/lens-proxy.ts +++ b/src/main/lens-proxy.ts @@ -97,6 +97,7 @@ export class LensProxy extends Singleton { }); this.port = port; + process.env.LENS_PROXY_PORT = port.toString(); resolve(); }) .once("error", (error) => { diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index 13045bc496..88d7dff0af 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -31,6 +31,7 @@ import { IpcRendererNavigationEvents } from "../renderer/navigation/events"; import logger from "./logger"; import { productName } from "../common/vars"; import { LensProxy } from "./lens-proxy"; +import * as path from "path"; function isHideable(window: BrowserWindow | null): boolean { return Boolean(window && !window.isDestroyed()); @@ -84,6 +85,7 @@ export class WindowManager extends Singleton { titleBarStyle: "hidden", backgroundColor: "#1e2124", webPreferences: { + preload: path.join(__static, "build", "preload.js"), nodeIntegration: true, nodeIntegrationInSubFrames: true, enableRemoteModule: true, diff --git a/src/preload.ts b/src/preload.ts new file mode 100644 index 0000000000..0b8c68e2e4 --- /dev/null +++ b/src/preload.ts @@ -0,0 +1,29 @@ +/** + * 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 fetch from "node-fetch"; +import AbortController from "abort-controller"; + +window.AbortController = AbortController; + +export { + fetch +}; diff --git a/src/renderer/api/index.ts b/src/renderer/api/index.ts index 39ab671bc1..054dac794f 100644 --- a/src/renderer/api/index.ts +++ b/src/renderer/api/index.ts @@ -20,6 +20,7 @@ */ import type { JsonApiErrorParsed } from "../../common/k8s-api/json-api"; +import type { Response } from "node-fetch"; import { Notifications } from "../components/notifications"; import { apiBase, apiKube } from "../../common/k8s-api"; export { apiBase, apiKube } from "../../common/k8s-api"; @@ -35,5 +36,5 @@ export function onApiError(error: JsonApiErrorParsed, res: Response) { } } -apiBase.onError.addListener(onApiError); -apiKube.onError.addListener(onApiError); +if (apiBase) apiBase.onError.addListener(onApiError); +if (apiKube) apiKube.onError.addListener(onApiError); diff --git a/webpack.main.ts b/webpack.main.ts index ae78d06d09..6f95d2a65f 100755 --- a/webpack.main.ts +++ b/webpack.main.ts @@ -22,13 +22,15 @@ import path from "path"; import type webpack from "webpack"; import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin"; -import { isProduction, mainDir, buildDir, isDevelopment } from "./src/common/vars"; +import { isProduction, mainDir, buildDir, isDevelopment, preloadEntrypoint } from "./src/common/vars"; import nodeExternals from "webpack-node-externals"; import ProgressBarPlugin from "progress-bar-webpack-plugin"; import * as vars from "./src/common/vars"; import getTSLoader from "./src/common/getTSLoader"; -export default function (): webpack.Configuration { +const configs: {(): webpack.Configuration}[] = []; + +configs.push((): webpack.Configuration => { console.info("WEBPACK:main", vars); return { @@ -64,4 +66,45 @@ export default function (): webpack.Configuration { new ForkTsCheckerPlugin(), ].filter(Boolean) }; -} +}); + +configs.push((): webpack.Configuration => { + console.info("WEBPACK:preload", vars); + + return { + context: __dirname, + target: "electron-main", + mode: isProduction ? "production" : "development", + devtool: isProduction ? "source-map" : "cheap-eval-source-map", + cache: isDevelopment, + entry: { + main: path.resolve(preloadEntrypoint), + }, + output: { + libraryTarget: "global", + path: buildDir, + filename: "preload.js" + }, + resolve: { + extensions: [".json", ".js", ".ts"] + }, + externals: [ + nodeExternals() + ], + module: { + rules: [ + { + test: /\.node$/, + use: "node-loader" + }, + getTSLoader(/\.ts$/) + ] + }, + plugins: [ + new ProgressBarPlugin(), + new ForkTsCheckerPlugin(), + ].filter(Boolean) + }; +}); + +export default configs; diff --git a/yarn.lock b/yarn.lock index d123635946..962fa715a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1685,6 +1685,14 @@ resolved "https://registry.yarnpkg.com/@types/module-alias/-/module-alias-2.0.0.tgz#882668f8b8cdbda44812c3b592c590909e18849e" integrity sha512-e3sW4oEH0qS1QxSfX7PT6xIi5qk/YSMsrB9Lq8EtkhQBZB+bKyfkP+jpLJRySanvBhAQPSv2PEBe81M8Iy/7yg== +"@types/node-fetch@^2.5.12": + version "2.5.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" + integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": version "14.14.41" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615" @@ -4102,7 +4110,7 @@ columnify@~1.5.4: strip-ansi "^3.0.0" wcwidth "^1.0.0" -combined-stream@^1.0.6, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -4439,13 +4447,6 @@ cross-fetch@^3.0.4: dependencies: node-fetch "2.6.1" -cross-fetch@^3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39" - integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ== - dependencies: - node-fetch "2.6.1" - cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -6422,6 +6423,15 @@ form-data@^2.5.0: combined-stream "^1.0.6" mime-types "^2.1.12" +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -10181,7 +10191,7 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" -node-fetch@2.6.1: +node-fetch@2.6.1, node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==