1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00
lens/build/download_kubectl.ts
Sebastian Malton 47fbf629ea remove depricated package request from our code
Signed-off-by: Sebastian Malton <smalton@mirantis.com>
2021-04-01 12:46:17 -04:00

123 lines
3.6 KiB
TypeScript

import fs from "fs";
import fse from "fs-extra";
import got from "got/dist/source";
import md5File from "md5-file";
import path from "path";
import stream from "stream";
import util, { promisify } from "util";
import packageInfo from "../package.json";
import { GotStreamFunctionOptions } from "../src/common/got-opts";
import logger from "../src/main/logger";
const pipeline = promisify(stream.pipeline);
class KubectlDownloader {
public kubectlVersion: string;
protected url: string;
protected path: string;
protected dirname: string;
constructor(clusterVersion: string, platform: string, arch: string, target: string) {
this.kubectlVersion = clusterVersion;
const binaryName = platform === "windows" ? "kubectl.exe" : "kubectl";
this.url = `https://storage.googleapis.com/kubernetes-release/release/v${this.kubectlVersion}/bin/${platform}/${arch}/${binaryName}`;
this.dirname = path.dirname(target);
this.path = target;
}
protected async urlEtag() {
try {
const res = await got.head(this.url);
const { etag } = res.headers;
if (Array.isArray(etag)) {
return etag[0].replace(/"/g, "");
}
if (typeof etag === "string") {
return etag.replace(/"/g, "");
}
} catch (err) {
logger.error("Failed to get etag:", err);
}
return "";
}
public async checkBinary() {
const exists = await fse.pathExists(this.path);
if (exists) {
const hash = md5File.sync(this.path);
const etag = await this.urlEtag();
if(hash == etag) {
console.log("Kubectl md5sum matches the remote etag");
return true;
}
console.log(`Kubectl md5sum ${hash} does not match the remote etag ${etag}, unlinking and downloading again`);
await fs.promises.unlink(this.path);
}
return false;
}
public async downloadKubectl(): Promise<void> {
const exists = await this.checkBinary();
if (exists) {
return void console.log("Already exists and is valid");
}
await fse.ensureDir(path.dirname(this.path), 0o755);
console.log(`Downloading kubectl ${this.kubectlVersion} from ${this.url} to ${this.path}`);
const options: GotStreamFunctionOptions = {
decompress: true,
isStream: true,
};
try {
// TODO: improve the UI for this to use some sort of loading bar TUI
await pipeline(
got.stream(this.url, options),
fs.createWriteStream(this.path)
);
await fse.chmod(this.path, 0o755);
} catch (err) {
logger.error("Failed to download kubectl:", err);
}
}
}
const downloadVersion = packageInfo.config.bundledKubectlVersion;
const baseDir = path.join(process.env.INIT_CWD, "binaries", "client");
interface DownloadTarget {
platform: string;
target: string;
arch: string;
}
const downloads: DownloadTarget[] = [
{ platform: "linux", arch: "amd64", target: path.join(baseDir, "linux", "x64", "kubectl") },
{ platform: "darwin", arch: "amd64", target: path.join(baseDir, "darwin", "x64", "kubectl") },
{ platform: "windows", arch: "amd64", target: path.join(baseDir, "windows", "x64", "kubectl.exe") },
{ platform: "windows", arch: "386", target: path.join(baseDir, "windows", "ia32", "kubectl.exe") }
];
async function downloadOne(opts: DownloadTarget) {
const downloader = new KubectlDownloader(downloadVersion, opts.platform, opts.arch, opts.target);
console.log(`Downloading: ${util.inspect(opts, false, null, true)}`);
await downloader.downloadKubectl();
await downloader.checkBinary();
console.log(`Finished downloading for ${opts.platform}/${opts.arch}`);
}
Promise.all(downloads.map(downloadOne));