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

fix changing to got

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-03-10 14:29:19 -05:00
parent 0b98f59f59
commit 07b75b8027
14 changed files with 70 additions and 97 deletions

View File

@ -234,8 +234,6 @@
"react-dom": "^17.0.1",
"react-router": "^5.2.0",
"readable-stream": "^3.6.0",
"request": "^2.88.2",
"request-promise-native": "^1.0.8",
"semver": "^7.3.2",
"serializr": "^2.0.3",
"shell-env": "^3.0.1",
@ -291,8 +289,6 @@
"@types/react-select": "^3.0.13",
"@types/react-window": "^1.8.2",
"@types/readable-stream": "^2.3.9",
"@types/request": "^2.48.5",
"@types/request-promise-native": "^1.0.17",
"@types/semver": "^7.2.0",
"@types/sharp": "^0.26.0",
"@types/shelljs": "^0.8.8",

View File

@ -1,4 +1,4 @@
import requestPromise from "request-promise-native";
import got from "got/dist/source";
import packageInfo from "../../../package.json";
export function getAppVersion(): string {
@ -14,11 +14,7 @@ export function getBundledExtensions(): string[] {
}
export async function getAppVersionFromProxyServer(proxyPort: number): Promise<string> {
const response = await requestPromise({
method: "GET",
uri: `http://localhost:${proxyPort}/version`,
resolveWithFullResponse: true
});
const responseJson = await got(`http://localhost:${proxyPort}/version`).json<any>();
return JSON.parse(response.body).version;
return responseJson.version;
}

View File

@ -1,4 +1,4 @@
import request from "request";
import got, { CancelableRequest } from "got";
export interface DownloadFileOptions {
url: string;
@ -6,32 +6,6 @@ export interface DownloadFileOptions {
timeout?: number;
}
export interface DownloadFileTicket {
url: string;
promise: Promise<Buffer>;
cancel(): void;
}
export function downloadFile({ url, timeout, gzip = true }: DownloadFileOptions): DownloadFileTicket {
const fileChunks: Buffer[] = [];
const req = request(url, { gzip, timeout });
const promise: Promise<Buffer> = new Promise((resolve, reject) => {
req.on("data", (chunk: Buffer) => {
fileChunks.push(chunk);
});
req.once("error", err => {
reject({ url, err });
});
req.once("complete", () => {
resolve(Buffer.concat(fileChunks));
});
});
return {
url,
promise,
cancel() {
req.abort();
}
};
export function downloadFile({ url, timeout, gzip = true }: DownloadFileOptions): CancelableRequest<Buffer> {
return got(url, { timeout, decompress: gzip }).buffer();
}

View File

@ -1,5 +1,5 @@
import request, { RequestPromiseOptions } from "request-promise-native";
import { Cluster } from "../cluster";
import { OptionsOfJSONResponseBody, Response } from "got";
import { Cluster, k8sRequest } from "../cluster";
export type ClusterDetectionResult = {
value: string | number | boolean
@ -18,17 +18,10 @@ export class BaseClusterDetector {
return null;
}
protected async k8sRequest<T = any>(path: string, options: RequestPromiseOptions = {}): Promise<T> {
const apiUrl = this.cluster.kubeProxyUrl + path;
protected async k8sRequest<T>(path: string, options: OptionsOfJSONResponseBody = {}): Promise<[Response<T>, T]> {
options.headers ??= {};
options.headers["Host"] ??= `${this.cluster.id}.${this.cluster.kubeProxyUrl.host}`; // required in ClusterManager.getClusterForRequest()''
return request(apiUrl, {
json: true,
timeout: 30000,
...options,
headers: {
Host: `${this.cluster.id}.${this.cluster.kubeProxyUrl.host}`, // required in ClusterManager.getClusterForRequest()
...(options.headers || {}),
},
});
return k8sRequest(this.cluster.getUrlTo(path), options);
}
}

View File

@ -19,8 +19,8 @@ export class ClusterIdDetector extends BaseClusterDetector {
}
protected async getDefaultNamespaceId() {
const response = await this.k8sRequest("/api/v1/namespaces/default");
const [, responseJson] = await this.k8sRequest<any>("/api/v1/namespaces/default");
return response.metadata.uid;
return responseJson.metadata.uid;
}
}

View File

@ -39,7 +39,7 @@ export class DistributionDetector extends BaseClusterDetector {
if (this.isK0s()) {
return { value: "k0s", accuracy: 80};
}
if (this.isVMWare()) {
return { value: "vmware", accuracy: 90};
}
@ -90,9 +90,9 @@ export class DistributionDetector extends BaseClusterDetector {
public async getKubernetesVersion() {
if (this.cluster.version) return this.cluster.version;
const response = await this.k8sRequest("/version");
const [,responseJson] = await this.k8sRequest<any>("/version");
return response.gitVersion;
return responseJson.gitVersion;
}
protected isGKE() {
@ -158,7 +158,7 @@ export class DistributionDetector extends BaseClusterDetector {
protected isK0s() {
return this.version.includes("-k0s");
}
protected isAlibaba() {
return this.version.includes("-aliyun");
}
@ -169,9 +169,9 @@ export class DistributionDetector extends BaseClusterDetector {
protected async isOpenshift() {
try {
const response = await this.k8sRequest("");
const [, responseJson] = await this.k8sRequest<any>("");
return response.paths?.includes("/apis/project.openshift.io");
return responseJson.paths?.includes("/apis/project.openshift.io");
} catch (e) {
return false;
}

View File

@ -7,7 +7,7 @@ export class LastSeenDetector extends BaseClusterDetector {
public async detect() {
if (!this.cluster.accessible) return null;
await this.k8sRequest("/version");
await this.k8sRequest<any>("/version");
return { value: new Date().toJSON(), accuracy: 100 };
}

View File

@ -12,8 +12,8 @@ export class NodesCountDetector extends BaseClusterDetector {
}
protected async getNodeCount(): Promise<number> {
const response = await this.k8sRequest("/api/v1/nodes");
const [, responseJson] = await this.k8sRequest<any>("/api/v1/nodes");
return response.items.length;
return responseJson.items.length;
}
}

View File

@ -12,8 +12,8 @@ export class VersionDetector extends BaseClusterDetector {
}
public async getKubernetesVersion() {
const response = await this.k8sRequest("/version");
const [, responseJson] = await this.k8sRequest<any>("/version", { retry: 0 });
return response.gitVersion;
return responseJson.gitVersion;
}
}

View File

@ -14,7 +14,7 @@ import logger from "./logger";
import { VersionDetector } from "./cluster-detectors/version-detector";
import { detectorRegistry } from "./cluster-detectors/detector-registry";
import plimit from "p-limit";
import got, { OptionsOfJSONResponseBody } from "got";
import got, { OptionsOfJSONResponseBody, Response } from "got";
import { URL } from "url";
export enum ClusterStatus {
@ -51,6 +51,24 @@ export interface ClusterState {
isGlobalWatchEnabled: boolean;
}
export async function k8sRequest<T = any>(url: string | URL, options: OptionsOfJSONResponseBody = {}): Promise<[Response<T>, T]> {
options.timeout ??= 5000;
options.headers ??= {};
options.headers["content-type"] ??= "application/json";
options.throwHttpErrors ??= true;
try {
const resp = got<T>(url, options);
const jsonResp = resp.json<T>();
return await Promise.all([resp, jsonResp]);
} catch(error) {
logger.error(`[REQUEST]: failed to get ${url}`, { error });
throw error;
}
}
/**
* Cluster
*
@ -495,7 +513,7 @@ export class Cluster implements ClusterModel, ClusterState {
return this.kubeconfigManager.getPath();
}
private getUrlTo(path: string): URL {
public getUrlTo(path: string): URL {
const url = new URL(this.kubeProxyUrl.toString());
url.pathname += path;
@ -538,34 +556,36 @@ export class Cluster implements ClusterModel, ClusterState {
const versionData = await versionDetector.detect();
this.metadata.version = versionData.value;
this.failureReason = null;
return ClusterStatus.AccessGranted;
} catch (error) {
logger.error(`Failed to connect cluster "${this.contextName}": ${error}`);
logger.error(`Failed to connect cluster "${this.contextName}"`, { error });
if (error instanceof got.TimeoutError) {
this.failureReason = "Connection timed out";
return ClusterStatus.Offline;
}
if (error.statusCode) {
if (error.statusCode >= 400 && error.statusCode < 500) {
this.failureReason = "Invalid credentials";
return ClusterStatus.AccessDenied;
} else {
this.failureReason = error.error || error.message;
return ClusterStatus.Offline;
}
} else if (error.failed === true) {
if (error.timedOut === true) {
this.failureReason = "Connection timed out";
return ClusterStatus.Offline;
} else {
this.failureReason = "Failed to fetch credentials";
this.failureReason = error.error || error.message;
return ClusterStatus.AccessDenied;
}
return ClusterStatus.Offline;
}
if (error.failed === true) {
this.failureReason = "Failed to fetch credentials";
return ClusterStatus.AccessDenied;
}
this.failureReason = error.message;
return ClusterStatus.Offline;

View File

@ -12,15 +12,17 @@ export interface MetricsQuery {
// prometheus metrics loader
async function loadMetrics(promQueries: string[], cluster: Cluster, prometheusPath: string, queryParams: Record<string, string>): Promise<any[]> {
const queries = promQueries.map(p => p.trim());
const loaders = new Map<string, Promise<any>>();
const loaders = new Map<string, ReturnType<(typeof cluster)["getMetrics"]>>();
async function loadMetric(query: string): Promise<any> {
async function loadMetric(query: string) {
const searchParams = { query, ...queryParams };
return loaders.get(query) ?? loaders.set(query, cluster.getMetrics(prometheusPath, { searchParams, retry: 5 })).get(query);
}
return Promise.all(queries.map(loadMetric));
const responses = await Promise.all(queries.map(loadMetric));
return responses.map(([, respJson]) => respJson);
}
export interface MetricsResult {
@ -69,7 +71,7 @@ class MetricsRoute extends LensApi {
}
prometheusMetadata.success = true;
} catch (error) {
logger.error("[METRICS]: failed to load metrics", { error });
logger.error(`[METRICS]: failed to load metrics: ${error}`, { error });
prometheusMetadata.success = false;
this.respondJson(response, {});

View File

@ -170,8 +170,7 @@ export class Extensions extends React.Component {
// install via url
// fixme: improve error messages for non-tar-file URLs
if (InputValidators.isUrl.validate(installPath)) {
const { promise: filePromise } = downloadFile({ url: installPath, timeout: 60000 /*1m*/ });
const data = await filePromise;
const data = await downloadFile({ url: installPath, timeout: 60000 /*1m*/ });
await this.requestInstall({ fileName, data });
}

View File

@ -44,7 +44,7 @@ export class ClustersMenu extends React.Component<Props> {
click: actions.showSettings
}));
if (cluster.online) {
if (cluster.online || cluster.failureReason) {
menu.append(new MenuItem({
label: `Disconnect`,
click: actions.disconnect

View File

@ -1682,14 +1682,7 @@
resolved "https://registry.yarnpkg.com/@types/relateurl/-/relateurl-0.2.28.tgz#6bda7db8653fa62643f5ee69e9f69c11a392e3a6"
integrity sha1-a9p9uGU/piZD9e5p6facEaOS46Y=
"@types/request-promise-native@^1.0.17":
version "1.0.17"
resolved "https://registry.yarnpkg.com/@types/request-promise-native/-/request-promise-native-1.0.17.tgz#74a2d7269aebf18b9bdf35f01459cf0a7bfc7fab"
integrity sha512-05/d0WbmuwjtGMYEdHIBZ0tqMJJQ2AD9LG2F6rKNBGX1SSFR27XveajH//2N/XYtual8T9Axwl+4v7oBtPUZqg==
dependencies:
"@types/request" "*"
"@types/request@*", "@types/request@^2.47.1", "@types/request@^2.48.5":
"@types/request@^2.47.1":
version "2.48.5"
resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.5.tgz#019b8536b402069f6d11bee1b2c03e7f232937a0"
integrity sha512-/LO7xRVnL3DxJ1WkPGDQrp4VTV1reX9RkC85mJ+Qzykj2Bdw+mG15aAfDahc76HtknjzE16SX/Yddn6MxVbmGQ==