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

switch to use node-fetch on both sides

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen 2021-08-05 11:21:26 +03:00
parent 4b8ea266b8
commit 98e708fa01
49 changed files with 596 additions and 164 deletions

View File

@ -15,7 +15,7 @@
"dev": "concurrently -i -k \"yarn run dev-run -C\" yarn:dev:*", "dev": "concurrently -i -k \"yarn run dev-run -C\" yarn:dev:*",
"dev-build": "concurrently yarn:compile:*", "dev-build": "concurrently yarn:compile:*",
"debug-build": "concurrently yarn:compile:main yarn:compile:extension-types", "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:main": "yarn run compile:main --watch",
"dev:renderer": "yarn run webpack-dev-server --config webpack.renderer.ts", "dev:renderer": "yarn run webpack-dev-server --config webpack.renderer.ts",
"dev:extension-types": "yarn run compile:extension-types --watch", "dev:extension-types": "yarn run compile:extension-types --watch",
@ -196,7 +196,6 @@
"chokidar": "^3.4.3", "chokidar": "^3.4.3",
"command-exists": "1.2.9", "command-exists": "1.2.9",
"conf": "^7.0.1", "conf": "^7.0.1",
"cross-fetch": "^3.1.4",
"crypto-js": "^4.0.0", "crypto-js": "^4.0.0",
"electron-devtools-installer": "^3.2.0", "electron-devtools-installer": "^3.2.0",
"electron-updater": "^4.3.1", "electron-updater": "^4.3.1",
@ -222,6 +221,7 @@
"mock-fs": "^4.14.0", "mock-fs": "^4.14.0",
"moment": "^2.29.1", "moment": "^2.29.1",
"moment-timezone": "^0.5.33", "moment-timezone": "^0.5.33",
"node-fetch": "^2.6.1",
"node-pty": "^0.10.1", "node-pty": "^0.10.1",
"npm": "^6.14.8", "npm": "^6.14.8",
"openid-client": "^3.15.2", "openid-client": "^3.15.2",
@ -284,6 +284,7 @@
"@types/mock-fs": "^4.13.1", "@types/mock-fs": "^4.13.1",
"@types/module-alias": "^2.0.0", "@types/module-alias": "^2.0.0",
"@types/node": "12.20", "@types/node": "12.20",
"@types/node-fetch": "^2.5.12",
"@types/npm": "^2.0.31", "@types/npm": "^2.0.31",
"@types/progress-bar-webpack-plugin": "^2.1.2", "@types/progress-bar-webpack-plugin": "^2.1.2",
"@types/proper-lockfile": "^4.1.1", "@types/proper-lockfile": "^4.1.1",

View File

@ -49,6 +49,8 @@ export class ApiManager {
} }
registerApi(apiBase: string, api: KubeApi<KubeObject>) { registerApi(apiBase: string, api: KubeApi<KubeObject>) {
if (!api.apiBase) return;
if (!this.apis.has(apiBase)) { if (!this.apis.has(apiBase)) {
this.stores.forEach((store) => { this.stores.forEach((store) => {
if (store.api === api) { if (store.api === api) {
@ -84,8 +86,8 @@ export class ApiManager {
@action @action
registerStore(store: KubeObjectStore<KubeObject>, apis: KubeApi<KubeObject>[] = [store.api]) { registerStore(store: KubeObjectStore<KubeObject>, apis: KubeApi<KubeObject>[] = [store.api]) {
apis.forEach(api => { apis.filter(Boolean).forEach(api => {
this.stores.set(api.apiBase, store); if (api.apiBase) this.stores.set(api.apiBase, store);
}); });
} }

View File

@ -18,6 +18,7 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * 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. * 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 { KubeApi } from "../kube-api";
import { KubeObject } from "../kube-object"; 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<ClusterRoleBinding>;
if (isClusterPageContext()) {
clusterRoleBindingApi = new KubeApi({
objectConstructor: ClusterRoleBinding,
});
}
export {
clusterRoleBindingApi
};

View File

@ -19,6 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { KubeObject } from "../kube-object"; 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<ClusterRole>;
if (isClusterPageContext()) { // initialize automatically only when within a cluster iframe/context
clusterRoleApi = new KubeApi({
objectConstructor: ClusterRole,
});
}
export {
clusterRoleApi
};

View File

@ -22,6 +22,7 @@
import { IMetrics, IMetricsReqParams, metricsApi } from "./metrics.api"; import { IMetrics, IMetricsReqParams, metricsApi } from "./metrics.api";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class ClusterApi extends KubeApi<Cluster> { export class ClusterApi extends KubeApi<Cluster> {
static kind = "Cluster"; 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
};

View File

@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface ConfigMap { export interface ConfigMap {
data: { 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<ConfigMap>;
if (isClusterPageContext()) {
configMapApi = new KubeApi({
objectConstructor: ConfigMap,
});
}
export {
configMapApi
};

View File

@ -22,6 +22,7 @@
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { crdResourcesURL } from "../../routes"; import { crdResourcesURL } from "../../routes";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
type AdditionalPrinterColumnsCommon = { type AdditionalPrinterColumnsCommon = {
name: string; name: string;
@ -174,7 +175,18 @@ export class CustomResourceDefinition extends KubeObject {
} }
} }
export const crdApi = new KubeApi<CustomResourceDefinition>({ /**
objectConstructor: CustomResourceDefinition, * Only available within kubernetes cluster pages
checkPreferredVersion: true, */
}); let crdApi: KubeApi<CustomResourceDefinition>;
if (isClusterPageContext()) {
crdApi = new KubeApi<CustomResourceDefinition>({
objectConstructor: CustomResourceDefinition,
checkPreferredVersion: true,
});
}
export {
crdApi
};

View File

@ -26,6 +26,7 @@ import { formatDuration } from "../../utils/formatDuration";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class CronJobApi extends KubeApi<CronJob> { export class CronJobApi extends KubeApi<CronJob> {
suspend(params: { namespace: string; name: string }) { 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
};

View File

@ -26,6 +26,7 @@ import { KubeApi } from "../kube-api";
import { metricsApi } from "./metrics.api"; import { metricsApi } from "./metrics.api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import type { IPodContainer, IPodMetrics } from "./pods.api"; import type { IPodContainer, IPodMetrics } from "./pods.api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class DaemonSet extends WorkloadKubeObject { export class DaemonSet extends WorkloadKubeObject {
static kind = "DaemonSet"; 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
};

View File

@ -27,6 +27,7 @@ import { KubeApi } from "../kube-api";
import { metricsApi } from "./metrics.api"; import { metricsApi } from "./metrics.api";
import type { IPodMetrics } from "./pods.api"; import type { IPodMetrics } from "./pods.api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class DeploymentApi extends KubeApi<Deployment> { export class DeploymentApi extends KubeApi<Deployment> {
protected getScaleApiUrl(params: { namespace: string; name: string }) { protected getScaleApiUrl(params: { namespace: string; name: string }) {
@ -232,6 +233,14 @@ export class Deployment extends WorkloadKubeObject {
} }
} }
export const deploymentApi = new DeploymentApi({ let deploymentApi: DeploymentApi;
objectConstructor: Deployment,
}); if (isClusterPageContext()) {
deploymentApi = new DeploymentApi({
objectConstructor: Deployment,
});
}
export {
deploymentApi
};

View File

@ -24,6 +24,7 @@ import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { get } from "lodash"; import { get } from "lodash";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface IEndpointPort { export interface IEndpointPort {
name?: string; name?: string;
@ -149,6 +150,14 @@ export class Endpoint extends KubeObject {
} }
export const endpointApi = new KubeApi({ let endpointApi: KubeApi<Endpoint>;
objectConstructor: Endpoint,
}); if (isClusterPageContext()) {
endpointApi = new KubeApi<Endpoint>({
objectConstructor: Endpoint,
});
}
export {
endpointApi
};

View File

@ -23,6 +23,7 @@ import moment from "moment";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { formatDuration } from "../../utils/formatDuration"; import { formatDuration } from "../../utils/formatDuration";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface KubeEvent { export interface KubeEvent {
involvedObject: { involvedObject: {
@ -77,6 +78,14 @@ export class KubeEvent extends KubeObject {
} }
} }
export const eventApi = new KubeApi({ let eventApi: KubeApi<KubeEvent>;
objectConstructor: KubeEvent,
}); if (isClusterPageContext()) {
eventApi = new KubeApi<KubeEvent>({
objectConstructor: KubeEvent,
});
}
export {
eventApi
};

View File

@ -23,6 +23,7 @@ import { compile } from "path-to-regexp";
import { apiBase } from "../index"; import { apiBase } from "../index";
import { stringify } from "querystring"; import { stringify } from "querystring";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import type { RequestInit } from "node-fetch";
export type RepoHelmChartList = Record<string, HelmChart[]>; export type RepoHelmChartList = Record<string, HelmChart[]>;
export type HelmChartList = Record<string, RepoHelmChartList>; export type HelmChartList = Record<string, RepoHelmChartList>;

View File

@ -21,6 +21,7 @@
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export enum HpaMetricType { export enum HpaMetricType {
Resource = "Resource", Resource = "Resource",
@ -163,6 +164,14 @@ export class HorizontalPodAutoscaler extends KubeObject {
} }
} }
export const hpaApi = new KubeApi({ let hpaApi: KubeApi<HorizontalPodAutoscaler>;
objectConstructor: HorizontalPodAutoscaler,
}); if (isClusterPageContext()) {
hpaApi = new KubeApi<HorizontalPodAutoscaler>({
objectConstructor: HorizontalPodAutoscaler,
});
}
export {
hpaApi
};

View File

@ -24,6 +24,7 @@ import { autoBind } from "../../utils";
import { IMetrics, metricsApi } from "./metrics.api"; import { IMetrics, metricsApi } from "./metrics.api";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class IngressApi extends KubeApi<Ingress> { export class IngressApi extends KubeApi<Ingress> {
} }
@ -203,10 +204,17 @@ export class Ingress extends KubeObject {
} }
} }
export const ingressApi = new IngressApi({ let ingressApi: IngressApi;
objectConstructor: Ingress,
// Add fallback for Kubernetes <1.19 if (isClusterPageContext()) {
checkPreferredVersion: true, ingressApi = new IngressApi({
fallbackApiBases: ["/apis/extensions/v1beta1/ingresses"], objectConstructor: Ingress,
logStuff: true // Add fallback for Kubernetes <1.19
} as any); checkPreferredVersion: true,
fallbackApiBases: ["/apis/extensions/v1beta1/ingresses"],
});
}
export {
ingressApi
};

View File

@ -27,6 +27,7 @@ import { metricsApi } from "./metrics.api";
import type { JsonApiParams } from "../json-api"; import type { JsonApiParams } from "../json-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import type { IPodContainer, IPodMetrics } from "./pods.api"; import type { IPodContainer, IPodMetrics } from "./pods.api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class Job extends WorkloadKubeObject { export class Job extends WorkloadKubeObject {
static kind = "Job"; static kind = "Job";
@ -148,6 +149,14 @@ export function getMetricsForJobs(jobs: Job[], namespace: string, selector = "")
}); });
} }
export const jobApi = new JobApi({ let jobApi: JobApi;
objectConstructor: Job,
}); if (isClusterPageContext()) {
jobApi = new JobApi({
objectConstructor: Job,
});
}
export {
jobApi
};

View File

@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export enum LimitType { export enum LimitType {
CONTAINER = "Container", CONTAINER = "Container",
@ -80,6 +81,14 @@ export class LimitRange extends KubeObject {
} }
} }
export const limitRangeApi = new KubeApi({ let limitRangeApi: KubeApi<LimitRange>;
objectConstructor: LimitRange,
}); if (isClusterPageContext()) {
limitRangeApi = new KubeApi<LimitRange>({
objectConstructor: LimitRange,
});
}
export {
limitRangeApi
};

View File

@ -25,6 +25,7 @@ import { autoBind } from "../../../renderer/utils";
import { metricsApi } from "./metrics.api"; import { metricsApi } from "./metrics.api";
import type { IPodMetrics } from "./pods.api"; import type { IPodMetrics } from "./pods.api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export enum NamespaceStatus { export enum NamespaceStatus {
ACTIVE = "Active", ACTIVE = "Active",
@ -69,6 +70,14 @@ export function getMetricsForNamespace(namespace: string, selector = ""): Promis
}); });
} }
export const namespacesApi = new NamespaceApi({ let namespacesApi: NamespaceApi;
objectConstructor: Namespace,
}); if (isClusterPageContext()) {
namespacesApi = new NamespaceApi({
objectConstructor: Namespace,
});
}
export {
namespacesApi
};

View File

@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface IPolicyIpBlock { export interface IPolicyIpBlock {
cidr: string; cidr: string;
@ -96,6 +97,14 @@ export class NetworkPolicy extends KubeObject {
} }
} }
export const networkPolicyApi = new KubeApi({ let networkPolicyApi: KubeApi<NetworkPolicy>;
objectConstructor: NetworkPolicy,
}); if (isClusterPageContext()) {
networkPolicyApi = new KubeApi<NetworkPolicy>({
objectConstructor: NetworkPolicy,
});
}
export {
networkPolicyApi
};

View File

@ -24,6 +24,7 @@ import { autoBind, cpuUnitsToNumber, unitsToBytes } from "../../../renderer/util
import { IMetrics, metricsApi } from "./metrics.api"; import { IMetrics, metricsApi } from "./metrics.api";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class NodesApi extends KubeApi<Node> { export class NodesApi extends KubeApi<Node> {
} }
@ -225,6 +226,14 @@ export class Node extends KubeObject {
} }
} }
export const nodesApi = new NodesApi({ let nodesApi: NodesApi;
objectConstructor: Node,
}); if (isClusterPageContext()) {
nodesApi = new NodesApi({
objectConstructor: Node,
});
}
export {
nodesApi
};

View File

@ -25,6 +25,7 @@ import { IMetrics, metricsApi } from "./metrics.api";
import type { Pod } from "./pods.api"; import type { Pod } from "./pods.api";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class PersistentVolumeClaimsApi extends KubeApi<PersistentVolumeClaim> { export class PersistentVolumeClaimsApi extends KubeApi<PersistentVolumeClaim> {
} }
@ -116,6 +117,14 @@ export class PersistentVolumeClaim extends KubeObject {
} }
} }
export const pvcApi = new PersistentVolumeClaimsApi({ let pvcApi: PersistentVolumeClaimsApi;
objectConstructor: PersistentVolumeClaim,
}); if (isClusterPageContext()) {
pvcApi = new PersistentVolumeClaimsApi({
objectConstructor: PersistentVolumeClaim,
});
}
export {
pvcApi
};

View File

@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object";
import { autoBind, unitsToBytes } from "../../utils"; import { autoBind, unitsToBytes } from "../../utils";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface PersistentVolume { export interface PersistentVolume {
spec: { spec: {
@ -101,6 +102,14 @@ export class PersistentVolume extends KubeObject {
} }
} }
export const persistentVolumeApi = new KubeApi({ let persistentVolumeApi: KubeApi<PersistentVolume>;
objectConstructor: PersistentVolume,
}); if (isClusterPageContext()) {
persistentVolumeApi = new KubeApi({
objectConstructor: PersistentVolume,
});
}
export {
persistentVolumeApi
};

View File

@ -21,6 +21,7 @@
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface PodMetrics { export interface PodMetrics {
timestamp: string; timestamp: string;
@ -40,6 +41,14 @@ export class PodMetrics extends KubeObject {
static apiBase = "/apis/metrics.k8s.io/v1beta1/pods"; static apiBase = "/apis/metrics.k8s.io/v1beta1/pods";
} }
export const podMetricsApi = new KubeApi({ let podMetricsApi: KubeApi<PodMetrics>;
objectConstructor: PodMetrics,
}); if (isClusterPageContext()) {
podMetricsApi = new KubeApi<PodMetrics>({
objectConstructor: PodMetrics,
});
}
export {
podMetricsApi
};

View File

@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface PodDisruptionBudget { export interface PodDisruptionBudget {
spec: { spec: {
@ -72,6 +73,14 @@ export class PodDisruptionBudget extends KubeObject {
} }
export const pdbApi = new KubeApi({ let pdbApi: KubeApi<PodDisruptionBudget>;
objectConstructor: PodDisruptionBudget,
}); if (isClusterPageContext()) {
pdbApi = new KubeApi({
objectConstructor: PodDisruptionBudget,
});
}
export {
pdbApi
};

View File

@ -24,6 +24,7 @@ import { autoBind } from "../../utils";
import { IMetrics, metricsApi } from "./metrics.api"; import { IMetrics, metricsApi } from "./metrics.api";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class PodsApi extends KubeApi<Pod> { export class PodsApi extends KubeApi<Pod> {
async getLogs(params: { namespace: string; name: string }, query?: IPodLogsQuery): Promise<string> { async getLogs(params: { namespace: string; name: string }, query?: IPodLogsQuery): Promise<string> {
@ -502,6 +503,14 @@ export class Pod extends WorkloadKubeObject {
} }
} }
export const podsApi = new PodsApi({ let podsApi: PodsApi;
objectConstructor: Pod,
}); if (isClusterPageContext()) {
podsApi = new PodsApi({
objectConstructor: Pod,
});
}
export {
podsApi
};

View File

@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface PodSecurityPolicy { export interface PodSecurityPolicy {
spec: { spec: {
@ -117,6 +118,14 @@ export class PodSecurityPolicy extends KubeObject {
} }
} }
export const pspApi = new KubeApi({ let pspApi: KubeApi<PodSecurityPolicy>;
objectConstructor: PodSecurityPolicy,
}); if (isClusterPageContext()) {
pspApi = new KubeApi({
objectConstructor: PodSecurityPolicy,
});
}
export {
pspApi
};

View File

@ -26,6 +26,7 @@ import { KubeApi } from "../kube-api";
import { metricsApi } from "./metrics.api"; import { metricsApi } from "./metrics.api";
import type { IPodContainer, IPodMetrics, Pod } from "./pods.api"; import type { IPodContainer, IPodMetrics, Pod } from "./pods.api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class ReplicaSetApi extends KubeApi<ReplicaSet> { export class ReplicaSetApi extends KubeApi<ReplicaSet> {
protected getScaleApiUrl(params: { namespace: string; name: string }) { protected getScaleApiUrl(params: { namespace: string; name: string }) {
@ -123,6 +124,14 @@ export class ReplicaSet extends WorkloadKubeObject {
} }
} }
export const replicaSetApi = new ReplicaSetApi({ let replicaSetApi: ReplicaSetApi;
objectConstructor: ReplicaSet,
}); if (isClusterPageContext()) {
replicaSetApi = new ReplicaSetApi({
objectConstructor: ReplicaSet,
});
}
export {
replicaSetApi
};

View File

@ -21,6 +21,7 @@
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface IResourceQuotaValues { export interface IResourceQuotaValues {
[quota: string]: string; [quota: string]: string;
@ -80,6 +81,14 @@ export class ResourceQuota extends KubeObject {
} }
} }
export const resourceQuotaApi = new KubeApi({ let resourceQuotaApi: KubeApi<ResourceQuota>;
objectConstructor: ResourceQuota,
}); if (isClusterPageContext()) {
resourceQuotaApi = new KubeApi<ResourceQuota>({
objectConstructor: ResourceQuota,
});
}
export {
resourceQuotaApi
};

View File

@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export type RoleBindingSubjectKind = "Group" | "ServiceAccount" | "User"; export type RoleBindingSubjectKind = "Group" | "ServiceAccount" | "User";
@ -61,6 +62,14 @@ export class RoleBinding extends KubeObject {
} }
} }
export const roleBindingApi = new KubeApi({ let roleBindingApi: KubeApi<RoleBinding>;
objectConstructor: RoleBinding,
}); if (isClusterPageContext()) {
roleBindingApi = new KubeApi({
objectConstructor: RoleBinding,
});
}
export {
roleBindingApi
};

View File

@ -21,6 +21,7 @@
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface Role { export interface Role {
rules: { rules: {
@ -41,6 +42,14 @@ export class Role extends KubeObject {
} }
} }
export const roleApi = new KubeApi({ let roleApi: KubeApi<Role>;
objectConstructor: Role,
}); if (isClusterPageContext()) {
roleApi = new KubeApi<Role>({
objectConstructor: Role,
});
}
export{
roleApi
};

View File

@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { autoBind } from "../../utils"; import { autoBind } from "../../utils";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export enum SecretType { export enum SecretType {
Opaque = "Opaque", Opaque = "Opaque",
@ -69,6 +70,14 @@ export class Secret extends KubeObject {
} }
} }
export const secretsApi = new KubeApi({ let secretsApi: KubeApi<Secret>;
objectConstructor: Secret,
}); if (isClusterPageContext()) {
secretsApi = new KubeApi({
objectConstructor: Secret,
});
}
export {
secretsApi
};

View File

@ -21,6 +21,7 @@
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class SelfSubjectRulesReviewApi extends KubeApi<SelfSubjectRulesReview> { export class SelfSubjectRulesReviewApi extends KubeApi<SelfSubjectRulesReview> {
create({ namespace = "default" }): Promise<SelfSubjectRulesReview> { create({ namespace = "default" }): Promise<SelfSubjectRulesReview> {
@ -86,6 +87,15 @@ export class SelfSubjectRulesReview extends KubeObject {
} }
} }
export const selfSubjectRulesReviewApi = new SelfSubjectRulesReviewApi({ let selfSubjectRulesReviewApi: SelfSubjectRulesReviewApi;
objectConstructor: SelfSubjectRulesReview,
}); if (isClusterPageContext()) {
selfSubjectRulesReviewApi = new SelfSubjectRulesReviewApi({
objectConstructor: SelfSubjectRulesReview,
});
}
export {
selfSubjectRulesReviewApi
};

View File

@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface ServiceAccount { export interface ServiceAccount {
secrets?: { secrets?: {
@ -52,6 +53,14 @@ export class ServiceAccount extends KubeObject {
} }
} }
export const serviceAccountsApi = new KubeApi<ServiceAccount>({ let serviceAccountsApi: KubeApi<ServiceAccount>;
objectConstructor: ServiceAccount,
}); if (isClusterPageContext()) {
serviceAccountsApi = new KubeApi<ServiceAccount>({
objectConstructor: ServiceAccount,
});
}
export {
serviceAccountsApi
};

View File

@ -23,6 +23,7 @@ import { autoBind } from "../../../renderer/utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface ServicePort { export interface ServicePort {
name?: string; name?: string;
@ -143,6 +144,14 @@ export class Service extends KubeObject {
} }
} }
export const serviceApi = new KubeApi({ let serviceApi: KubeApi<Service>;
objectConstructor: Service,
}); if (isClusterPageContext()) {
serviceApi = new KubeApi<Service>({
objectConstructor: Service,
});
}
export {
serviceApi
};

View File

@ -26,6 +26,7 @@ import { KubeApi } from "../kube-api";
import { metricsApi } from "./metrics.api"; import { metricsApi } from "./metrics.api";
import type { IPodContainer, IPodMetrics } from "./pods.api"; import type { IPodContainer, IPodMetrics } from "./pods.api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export class StatefulSetApi extends KubeApi<StatefulSet> { export class StatefulSetApi extends KubeApi<StatefulSet> {
protected getScaleApiUrl(params: { namespace: string; name: string }) { protected getScaleApiUrl(params: { namespace: string; name: string }) {
@ -149,6 +150,14 @@ export class StatefulSet extends WorkloadKubeObject {
} }
} }
export const statefulSetApi = new StatefulSetApi({ let statefulSetApi: StatefulSetApi;
objectConstructor: StatefulSet,
}); if (isClusterPageContext()) {
statefulSetApi = new StatefulSetApi({
objectConstructor: StatefulSet,
});
}
export {
statefulSetApi
};

View File

@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
import { KubeObject } from "../kube-object"; import { KubeObject } from "../kube-object";
import { KubeApi } from "../kube-api"; import { KubeApi } from "../kube-api";
import type { KubeJsonApiData } from "../kube-json-api"; import type { KubeJsonApiData } from "../kube-json-api";
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";;
export interface StorageClass { export interface StorageClass {
provisioner: string; // e.g. "storage.k8s.io/v1" provisioner: string; // e.g. "storage.k8s.io/v1"
@ -62,6 +63,14 @@ export class StorageClass extends KubeObject {
} }
} }
export const storageClassApi = new KubeApi({ let storageClassApi: KubeApi<StorageClass>;
objectConstructor: StorageClass,
}); if (isClusterPageContext()) {
storageClassApi = new KubeApi({
objectConstructor: StorageClass,
});
}
export {
storageClassApi
};

View File

@ -22,12 +22,34 @@
import { JsonApi } from "./json-api"; import { JsonApi } from "./json-api";
import { KubeJsonApi } from "./kube-json-api"; import { KubeJsonApi } from "./kube-json-api";
import { apiKubePrefix, apiPrefix, isDebugging, isDevelopment } from "../../common/vars"; import { apiKubePrefix, apiPrefix, isDebugging, isDevelopment } from "../../common/vars";
import { isClusterPageContext } from "../utils/cluster-id-url-parsing";
export const apiBase = new JsonApi({ let apiBase: JsonApi;
apiBase: apiPrefix, let apiKube: KubeJsonApi;
debug: isDevelopment || isDebugging,
}); if (isClusterPageContext()) {
export const apiKube = new KubeJsonApi({ apiBase = new JsonApi({
apiBase: apiKubePrefix, serverAddress: `http://127.0.0.1:${window.location.port}`,
debug: isDevelopment, 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
};

View File

@ -21,11 +21,10 @@
// Base http-service / json-api class // 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 { stringify } from "querystring";
import { EventEmitter } from "../../common/event-emitter"; import { EventEmitter } from "../../common/event-emitter";
import { randomBytes } from "crypto";
import { ipcRenderer } from "electron";
import logger from "../../common/logger"; import logger from "../../common/logger";
export interface JsonApiData { export interface JsonApiData {
@ -52,13 +51,14 @@ export interface JsonApiLog {
export interface JsonApiConfig { export interface JsonApiConfig {
apiBase: string; apiBase: string;
serverAddress: string;
debug?: boolean; debug?: boolean;
} }
export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> { export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
static reqInitDefault: RequestInit = { static reqInitDefault: RequestInit = {
headers: { headers: {
"content-type": "application/json" "content-type": "application/json",
"connection": "keep-alive"
} }
}; };
@ -68,7 +68,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
constructor(protected config: JsonApiConfig, protected reqInit?: RequestInit) { constructor(protected config: JsonApiConfig, protected reqInit?: RequestInit) {
this.config = Object.assign({}, JsonApi.configDefault, config); 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); this.parseResponse = this.parseResponse.bind(this);
} }
@ -80,18 +80,8 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
} }
getResponse(path: string, params?: P, init: RequestInit = {}): Promise<Response> { getResponse(path: string, params?: P, init: RequestInit = {}): Promise<Response> {
const reqPath = `${this.config.apiBase}${path}`; let reqUrl = `${this.config.serverAddress}${this.config.apiBase}${path}`;
let reqUrl: string; const reqInit: RequestInit = merge({}, this.reqInit, init);
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 };
const { query } = params || {} as P; const { query } = params || {} as P;
if (!reqInit.method) { if (!reqInit.method) {
@ -106,7 +96,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
this.writeLog({ this.writeLog({
method: reqInit.method.toUpperCase(), method: reqInit.method.toUpperCase(),
reqUrl: reqPath, reqUrl,
reqInit, reqInit,
}); });
@ -130,8 +120,8 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
} }
protected async request<D>(path: string, params?: P, init: RequestInit = {}) { protected async request<D>(path: string, params?: P, init: RequestInit = {}) {
let reqUrl = this.config.apiBase + path; let reqUrl = `${this.config.serverAddress}${this.config.apiBase}${path}`;
const reqInit: RequestInit = { ...this.reqInit, ...init }; const reqInit: RequestInit = merge({}, this.reqInit, init);
const { data, query } = params || {} as P; const { data, query } = params || {} as P;
if (data && !reqInit.body) { if (data && !reqInit.body) {
@ -205,11 +195,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
protected writeLog(log: JsonApiLog) { protected writeLog(log: JsonApiLog) {
if (!this.config.debug) return; if (!this.config.debug) return;
const { method, reqUrl, ...params } = log; 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); logger.info(`[JSON-API] request ${method} ${reqUrl}`, params);
} }
} }

View File

@ -31,9 +31,10 @@ import { createKubeApiURL, parseKubeApi } from "./kube-api-parse";
import { KubeObjectConstructor, KubeObject, KubeStatus } from "./kube-object"; import { KubeObjectConstructor, KubeObject, KubeStatus } from "./kube-object";
import byline from "byline"; import byline from "byline";
import type { IKubeWatchEvent } from "./kube-watch-api"; import type { IKubeWatchEvent } from "./kube-watch-api";
import { ReadableWebToNodeStream } from "../utils/readableStream";
import { KubeJsonApi, KubeJsonApiData } from "./kube-json-api"; import { KubeJsonApi, KubeJsonApiData } from "./kube-json-api";
import { noop } from "../utils"; import { noop } from "../utils";
import type { RequestInit } from "node-fetch";
import AbortController from "abort-controller";
export interface IKubeApiOptions<T extends KubeObject> { export interface IKubeApiOptions<T extends KubeObject> {
/** /**
@ -96,11 +97,12 @@ export interface IKubeApiCluster {
export function forCluster<T extends KubeObject>(cluster: IKubeApiCluster, kubeClass: KubeObjectConstructor<T>): KubeApi<T> { export function forCluster<T extends KubeObject>(cluster: IKubeApiCluster, kubeClass: KubeObjectConstructor<T>): KubeApi<T> {
const request = new KubeJsonApi({ const request = new KubeJsonApi({
serverAddress: `http://127.0.0.1:${process.env.LENS_PROXY_PORT}`,
apiBase: apiKubePrefix, apiBase: apiKubePrefix,
debug: isDevelopment, debug: isDevelopment,
}, { }, {
headers: { headers: {
"X-Cluster-ID": cluster.metadata.uid "Host": `${cluster.metadata.uid}.localhost:${process.env.LENS_PROXY_PORT}`
} }
}); });
@ -434,7 +436,7 @@ export class KubeApi<T extends KubeObject> {
}); });
const watchUrl = this.getWatchUrl(namespace); 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 responsePromise
.then(response => { .then(response => {
@ -442,10 +444,8 @@ export class KubeApi<T extends KubeObject> {
return callback(null, response); return callback(null, response);
} }
const nodeStream = new ReadableWebToNodeStream(response.body);
["end", "close", "error"].forEach((eventName) => { ["end", "close", "error"].forEach((eventName) => {
nodeStream.on(eventName, () => { response.body.on(eventName, () => {
if (errorReceived) return; // kubernetes errors should be handled in a callback if (errorReceived) return; // kubernetes errors should be handled in a callback
clearTimeout(timedRetry); clearTimeout(timedRetry);
@ -455,7 +455,7 @@ export class KubeApi<T extends KubeObject> {
}); });
}); });
byline(nodeStream).on("data", (line) => { byline(response.body).on("data", (line) => {
try { try {
const event: IKubeWatchEvent<KubeJsonApiData> = JSON.parse(line); const event: IKubeWatchEvent<KubeJsonApiData> = JSON.parse(line);
@ -473,7 +473,10 @@ export class KubeApi<T extends KubeObject> {
}); });
}) })
.catch(error => { .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); callback(null, error);
}); });

View File

@ -20,6 +20,7 @@
*/ */
import { JsonApi, JsonApiData, JsonApiError } from "./json-api"; import { JsonApi, JsonApiData, JsonApiError } from "./json-api";
import type { Response } from "node-fetch";
export interface KubeJsonApiListMetadata { export interface KubeJsonApiListMetadata {
resourceVersion: string; resourceVersion: string;

View File

@ -30,6 +30,8 @@ import { apiManager } from "./api-manager";
import { ensureObjectSelfLink, IKubeApiQueryParams, KubeApi } from "./kube-api"; import { ensureObjectSelfLink, IKubeApiQueryParams, KubeApi } from "./kube-api";
import { parseKubeApi } from "./kube-api-parse"; import { parseKubeApi } from "./kube-api-parse";
import type { KubeJsonApiData } from "./kube-json-api"; import type { KubeJsonApiData } from "./kube-json-api";
import type { RequestInit } from "node-fetch";
import AbortController from "abort-controller";
export interface KubeObjectStoreLoadingParams<K extends KubeObject> { export interface KubeObjectStoreLoadingParams<K extends KubeObject> {
namespaces: string[]; namespaces: string[];
@ -347,7 +349,7 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
const { signal } = abortController; const { signal } = abortController;
const callback = (data: IKubeWatchEvent<T>, error: any) => { const callback = (data: IKubeWatchEvent<T>, error: any) => {
if (!this.isLoaded || error instanceof DOMException) return; if (!this.isLoaded || error?.type === "aborted") return;
if (error instanceof Response) { if (error instanceof Response) {
if (error.status === 404 || error.status === 401) { if (error.status === 404 || error.status === 401) {

View File

@ -48,3 +48,12 @@ export function getClusterFrameUrl(clusterId: ClusterId) {
export function getHostedClusterId(): ClusterId | undefined { export function getHostedClusterId(): ClusterId | undefined {
return getClusterIdFromHost(location.host); 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);
}

View File

@ -42,6 +42,7 @@ export const publicPath = "/build/" as string;
// Webpack build paths // Webpack build paths
export const contextDir = process.cwd(); export const contextDir = process.cwd();
export const buildDir = path.join(contextDir, "static", publicPath); 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 mainDir = path.join(contextDir, "src/main");
export const rendererDir = path.join(contextDir, "src/renderer"); export const rendererDir = path.join(contextDir, "src/renderer");
export const htmlTemplate = path.resolve(rendererDir, "template.html"); export const htmlTemplate = path.resolve(rendererDir, "template.html");

View File

@ -97,6 +97,7 @@ export class LensProxy extends Singleton {
}); });
this.port = port; this.port = port;
process.env.LENS_PROXY_PORT = port.toString();
resolve(); resolve();
}) })
.once("error", (error) => { .once("error", (error) => {

View File

@ -31,6 +31,7 @@ import { IpcRendererNavigationEvents } from "../renderer/navigation/events";
import logger from "./logger"; import logger from "./logger";
import { productName } from "../common/vars"; import { productName } from "../common/vars";
import { LensProxy } from "./lens-proxy"; import { LensProxy } from "./lens-proxy";
import * as path from "path";
function isHideable(window: BrowserWindow | null): boolean { function isHideable(window: BrowserWindow | null): boolean {
return Boolean(window && !window.isDestroyed()); return Boolean(window && !window.isDestroyed());
@ -84,6 +85,7 @@ export class WindowManager extends Singleton {
titleBarStyle: "hidden", titleBarStyle: "hidden",
backgroundColor: "#1e2124", backgroundColor: "#1e2124",
webPreferences: { webPreferences: {
preload: path.join(__static, "build", "preload.js"),
nodeIntegration: true, nodeIntegration: true,
nodeIntegrationInSubFrames: true, nodeIntegrationInSubFrames: true,
enableRemoteModule: true, enableRemoteModule: true,

29
src/preload.ts Normal file
View File

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

View File

@ -20,6 +20,7 @@
*/ */
import type { JsonApiErrorParsed } from "../../common/k8s-api/json-api"; import type { JsonApiErrorParsed } from "../../common/k8s-api/json-api";
import type { Response } from "node-fetch";
import { Notifications } from "../components/notifications"; import { Notifications } from "../components/notifications";
import { apiBase, apiKube } from "../../common/k8s-api"; import { apiBase, apiKube } from "../../common/k8s-api";
export { 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); if (apiBase) apiBase.onError.addListener(onApiError);
apiKube.onError.addListener(onApiError); if (apiKube) apiKube.onError.addListener(onApiError);

View File

@ -22,13 +22,15 @@
import path from "path"; import path from "path";
import type webpack from "webpack"; import type webpack from "webpack";
import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin"; 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 nodeExternals from "webpack-node-externals";
import ProgressBarPlugin from "progress-bar-webpack-plugin"; import ProgressBarPlugin from "progress-bar-webpack-plugin";
import * as vars from "./src/common/vars"; import * as vars from "./src/common/vars";
import getTSLoader from "./src/common/getTSLoader"; import getTSLoader from "./src/common/getTSLoader";
export default function (): webpack.Configuration { const configs: {(): webpack.Configuration}[] = [];
configs.push((): webpack.Configuration => {
console.info("WEBPACK:main", vars); console.info("WEBPACK:main", vars);
return { return {
@ -64,4 +66,45 @@ export default function (): webpack.Configuration {
new ForkTsCheckerPlugin(), new ForkTsCheckerPlugin(),
].filter(Boolean) ].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;

View File

@ -1685,6 +1685,14 @@
resolved "https://registry.yarnpkg.com/@types/module-alias/-/module-alias-2.0.0.tgz#882668f8b8cdbda44812c3b592c590909e18849e" resolved "https://registry.yarnpkg.com/@types/module-alias/-/module-alias-2.0.0.tgz#882668f8b8cdbda44812c3b592c590909e18849e"
integrity sha512-e3sW4oEH0qS1QxSfX7PT6xIi5qk/YSMsrB9Lq8EtkhQBZB+bKyfkP+jpLJRySanvBhAQPSv2PEBe81M8Iy/7yg== 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@*": "@types/node@*":
version "14.14.41" version "14.14.41"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615" 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" strip-ansi "^3.0.0"
wcwidth "^1.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" version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@ -4439,13 +4447,6 @@ cross-fetch@^3.0.4:
dependencies: dependencies:
node-fetch "2.6.1" 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: cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5" version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 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" combined-stream "^1.0.6"
mime-types "^2.1.12" 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: form-data@~2.3.2:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" 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" json-parse-better-errors "^1.0.0"
safe-buffer "^5.1.1" safe-buffer "^5.1.1"
node-fetch@2.6.1: node-fetch@2.6.1, node-fetch@^2.6.1:
version "2.6.1" version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==