mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
reverting dashboard rendering to webview, part 1
This commit is contained in:
parent
d387ba9004
commit
d413235ed9
21
.babelrc
21
.babelrc
@ -1,10 +1,27 @@
|
|||||||
{
|
{
|
||||||
"presets": [
|
"presets": [
|
||||||
"@babel/preset-env",
|
[
|
||||||
|
"@babel/preset-env",
|
||||||
|
{
|
||||||
|
"modules": "commonjs",
|
||||||
|
"targets": {
|
||||||
|
"esmodules": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
"@babel/preset-react",
|
"@babel/preset-react",
|
||||||
"@lingui/babel-preset-react"
|
"@lingui/babel-preset-react"
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"macros"
|
"macros",
|
||||||
|
"@babel/plugin-syntax-dynamic-import",
|
||||||
|
[
|
||||||
|
"@babel/plugin-transform-runtime",
|
||||||
|
{
|
||||||
|
"absoluteRuntime": false,
|
||||||
|
"regenerator": true,
|
||||||
|
"useESModules": true
|
||||||
|
}
|
||||||
|
]
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,11 +5,11 @@
|
|||||||
"version": "3.5.0-beta.1",
|
"version": "3.5.0-beta.1",
|
||||||
"main": "dist/main.js",
|
"main": "dist/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "yarn compile:dll && concurrently yarn:dev:*",
|
"dev": "concurrently yarn:dev:*",
|
||||||
"dev-run": "electron --inspect .",
|
"dev-run": "electron --inspect .",
|
||||||
"dev:main": "DEBUG=true webpack --watch --progress --config webpack.main.ts",
|
"dev:main": "DEBUG=true webpack --watch --progress --config webpack.main.ts",
|
||||||
"dev:renderer": "DEBUG=true webpack --watch --progress --config webpack.renderer.ts",
|
"dev:renderer": "DEBUG=true webpack --watch --progress --config webpack.renderer.ts",
|
||||||
"compile": "NODE_ENV=production concurrently 'yarn download-bins' 'yarn i18n:compile' 'yarn compile:dll' && concurrently yarn:compile:*",
|
"compile": "NODE_ENV=production concurrently 'yarn download-bins' 'yarn i18n:compile' && concurrently yarn:compile:*",
|
||||||
"compile:main": "NODE_ENV=production webpack --progress --config webpack.main.ts $@",
|
"compile:main": "NODE_ENV=production webpack --progress --config webpack.main.ts $@",
|
||||||
"compile:renderer": "NODE_ENV=production webpack --progress --config webpack.renderer.ts $@",
|
"compile:renderer": "NODE_ENV=production webpack --progress --config webpack.renderer.ts $@",
|
||||||
"compile:dll": "webpack --config webpack.dll.ts $@",
|
"compile:dll": "webpack --config webpack.dll.ts $@",
|
||||||
@ -196,6 +196,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.10.2",
|
"@babel/core": "^7.10.2",
|
||||||
|
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.6.2",
|
||||||
"@babel/preset-env": "^7.10.2",
|
"@babel/preset-env": "^7.10.2",
|
||||||
"@babel/preset-react": "^7.10.1",
|
"@babel/preset-react": "^7.10.1",
|
||||||
"@babel/preset-typescript": "^7.10.1",
|
"@babel/preset-typescript": "^7.10.1",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { isMac, isWindows } from "./vars";
|
import { isMac, isWindows } from "./vars";
|
||||||
|
|
||||||
if (isMac) {
|
if (isMac) {
|
||||||
console.warn("//FIXME: MAC-CA IMPORT ERROR!");
|
// fixme: mac-ca import error
|
||||||
// require("mac-ca");
|
// require("mac-ca");
|
||||||
}
|
}
|
||||||
if (isWindows) {
|
if (isWindows) {
|
||||||
|
|||||||
@ -17,7 +17,6 @@ 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");
|
||||||
export const sassCommonVars = path.resolve(rendererDir, "components/vars.scss");
|
export const sassCommonVars = path.resolve(rendererDir, "components/vars.scss");
|
||||||
export const tsConfigFile = path.resolve(contextDir, "tsconfig.json");
|
|
||||||
|
|
||||||
// Apis
|
// Apis
|
||||||
export const staticProto = "static://"
|
export const staticProto = "static://"
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import { promises } from "fs"
|
|||||||
import { ensureDir } from "fs-extra"
|
import { ensureDir } from "fs-extra"
|
||||||
import filenamify from "filenamify"
|
import filenamify from "filenamify"
|
||||||
import { v4 as uuid } from "uuid"
|
import { v4 as uuid } from "uuid"
|
||||||
|
import { apiPrefix } from "../common/vars";
|
||||||
|
|
||||||
export type FeatureInstallRequest = {
|
export type FeatureInstallRequest = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -261,7 +262,7 @@ export class ClusterManager {
|
|||||||
cluster = this.clusters.get(clusterId)
|
cluster = this.clusters.get(clusterId)
|
||||||
if (cluster) {
|
if (cluster) {
|
||||||
// we need to swap path prefix so that request is proxied to kube api
|
// we need to swap path prefix so that request is proxied to kube api
|
||||||
req.url = req.url.replace(`/${clusterId}`, "/api-kube")
|
req.url = req.url.replace(`/${clusterId}`, apiPrefix.KUBE_BASE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { Kubectl } from "./kubectl";
|
|||||||
import { PromiseIpc } from "electron-promise-ipc"
|
import { PromiseIpc } from "electron-promise-ipc"
|
||||||
import request from "request-promise-native"
|
import request from "request-promise-native"
|
||||||
import { KubeconfigManager } from "./kubeconfig-manager"
|
import { KubeconfigManager } from "./kubeconfig-manager"
|
||||||
|
import { apiPrefix } from "../common/vars";
|
||||||
|
|
||||||
enum ClusterStatus {
|
enum ClusterStatus {
|
||||||
AccessGranted = 2,
|
AccessGranted = 2,
|
||||||
@ -180,7 +181,8 @@ export class Cluster implements ClusterInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async k8sRequest(path: string, opts: request.RequestPromiseOptions = {}) {
|
protected async k8sRequest(path: string, opts: request.RequestPromiseOptions = {}) {
|
||||||
const url = `http://127.0.0.1:${this.port}/api-kube${path}`; // fixme: remove hardcoded api prefix
|
const prefix = apiPrefix.KUBE_BASE;
|
||||||
|
const url = `http://127.0.0.1:${this.port}${prefix}${path}`;
|
||||||
opts.json = true;
|
opts.json = true;
|
||||||
opts.timeout = 10000;
|
opts.timeout = 10000;
|
||||||
opts.headers = Object.assign({}, opts.headers, {
|
opts.headers = Object.assign({}, opts.headers, {
|
||||||
|
|||||||
@ -1,23 +1,139 @@
|
|||||||
// Main process
|
// Main process
|
||||||
|
|
||||||
import "../common/system-ca"
|
import "../common/system-ca"
|
||||||
import { app, BrowserWindow } from "electron"
|
import "../common/prometheus-providers"
|
||||||
|
import { app, dialog, protocol } from "electron"
|
||||||
|
import { PromiseIpc } from "electron-promise-ipc"
|
||||||
|
import path from "path"
|
||||||
|
import { format as formatUrl } from "url"
|
||||||
|
import logger from "./logger"
|
||||||
|
import initMenu from "./menu"
|
||||||
|
import * as proxy from "./proxy"
|
||||||
|
import { WindowManager } from "./window-manager";
|
||||||
|
import { clusterStore } from "../common/cluster-store"
|
||||||
|
import { tracker } from "./tracker"
|
||||||
|
import { ClusterManager } from "./cluster-manager";
|
||||||
|
import AppUpdater from "./app-updater"
|
||||||
|
import { shellSync } from "./shell-sync"
|
||||||
|
import { getFreePort } from "./port"
|
||||||
|
import { mangleProxyEnv } from "./proxy-env"
|
||||||
|
import { findMainWebContents } from "./webcontents"
|
||||||
|
import { registerStaticProtocol } from "../common/register-static";
|
||||||
|
import { isMac } from "../common/vars";
|
||||||
|
|
||||||
console.log('MAIN', process.resourcesPath)
|
mangleProxyEnv()
|
||||||
console.log('userData', app.getPath("userData"))
|
if (app.commandLine.getSwitchValue("proxy-server") !== "") {
|
||||||
|
process.env.HTTPS_PROXY = app.commandLine.getSwitchValue("proxy-server")
|
||||||
|
}
|
||||||
|
|
||||||
app.whenReady().then(async function start() {
|
const promiseIpc = new PromiseIpc({ timeout: 2000 })
|
||||||
var mainWindow = new BrowserWindow({
|
let windowManager: WindowManager = null;
|
||||||
width: 1024,
|
let clusterManager: ClusterManager = null;
|
||||||
height: 768,
|
|
||||||
show: false,
|
|
||||||
webPreferences: {
|
|
||||||
devTools: true,
|
|
||||||
nodeIntegration: true,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await mainWindow.loadFile("dist/index.html");
|
const vmURL = formatUrl({
|
||||||
mainWindow.show();
|
pathname: path.join(__dirname, "dist/index.html"),
|
||||||
mainWindow.focus();
|
protocol: "file",
|
||||||
});
|
slashes: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
await shellSync()
|
||||||
|
|
||||||
|
const updater = new AppUpdater()
|
||||||
|
updater.start();
|
||||||
|
|
||||||
|
tracker.event("app", "start");
|
||||||
|
|
||||||
|
registerStaticProtocol();
|
||||||
|
protocol.registerFileProtocol('store', (request, callback) => {
|
||||||
|
const url = request.url.substr(8)
|
||||||
|
callback(path.normalize(`${app.getPath("userData")}/${url}`))
|
||||||
|
}, (error) => {
|
||||||
|
if (error) console.error('Failed to register protocol')
|
||||||
|
})
|
||||||
|
|
||||||
|
let port: number = null
|
||||||
|
// find free port
|
||||||
|
try {
|
||||||
|
port = await getFreePort()
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error)
|
||||||
|
await dialog.showErrorBox("Lens Error", "Could not find a free port for the cluster proxy")
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create cluster manager
|
||||||
|
clusterManager = new ClusterManager(clusterStore.getAllClusterObjects(), port)
|
||||||
|
|
||||||
|
// run proxy
|
||||||
|
try {
|
||||||
|
proxy.listen(port, clusterManager)
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`Could not start proxy (127.0.0:${port}): ${error.message}`)
|
||||||
|
await dialog.showErrorBox("Lens Error", `Could not start proxy (127.0.0:${port}): ${error.message || "unknown error"}`)
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// boot windowmanager
|
||||||
|
windowManager = new WindowManager();
|
||||||
|
windowManager.showMain(vmURL)
|
||||||
|
|
||||||
|
initMenu({
|
||||||
|
logoutHook: async () => {
|
||||||
|
// IPC send needs webContents as we're sending it to renderer
|
||||||
|
promiseIpc.send('logout', findMainWebContents(), {}).then((data: any) => {
|
||||||
|
logger.debug("logout IPC sent");
|
||||||
|
})
|
||||||
|
},
|
||||||
|
showPreferencesHook: async () => {
|
||||||
|
// IPC send needs webContents as we're sending it to renderer
|
||||||
|
promiseIpc.send('navigate', findMainWebContents(), { name: 'preferences-page' }).then((data: any) => {
|
||||||
|
logger.debug("navigate: preferences IPC sent");
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addClusterHook: async () => {
|
||||||
|
promiseIpc.send('navigate', findMainWebContents(), { name: "add-cluster-page" }).then((data: any) => {
|
||||||
|
logger.debug("navigate: add-cluster-page IPC sent");
|
||||||
|
})
|
||||||
|
},
|
||||||
|
showWhatsNewHook: async () => {
|
||||||
|
promiseIpc.send('navigate', findMainWebContents(), { name: "whats-new-page" }).then((data: any) => {
|
||||||
|
logger.debug("navigate: whats-new-page IPC sent");
|
||||||
|
})
|
||||||
|
},
|
||||||
|
clusterSettingsHook: async () => {
|
||||||
|
promiseIpc.send('navigate', findMainWebContents(), { name: "cluster-settings-page" }).then((data: any) => {
|
||||||
|
logger.debug("navigate: cluster-settings-page IPC sent");
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}, promiseIpc)
|
||||||
|
}
|
||||||
|
|
||||||
|
app.on("ready", main)
|
||||||
|
app.on('window-all-closed', function () {
|
||||||
|
// On OS X it is common for applications and their menu bar
|
||||||
|
// to stay active until the user quits explicitly with Cmd + Q
|
||||||
|
if (!isMac) {
|
||||||
|
app.quit();
|
||||||
|
} else {
|
||||||
|
windowManager = null
|
||||||
|
if (clusterManager) clusterManager.stop()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
app.on("activate", () => {
|
||||||
|
if (!windowManager) {
|
||||||
|
logger.debug("activate main window")
|
||||||
|
windowManager = new WindowManager(false)
|
||||||
|
windowManager.showMain(vmURL)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
app.on("will-quit", async (event) => {
|
||||||
|
event.preventDefault(); // To allow mixpanel sending to be executed
|
||||||
|
if (clusterManager) clusterManager.stop()
|
||||||
|
app.exit(0);
|
||||||
|
})
|
||||||
|
|
||||||
|
// todo: auto-restart app in dev-mode
|
||||||
|
// if (isDevelopment) {
|
||||||
|
// require('electron-reloader')(module);
|
||||||
|
// }
|
||||||
|
|||||||
@ -1,139 +0,0 @@
|
|||||||
// Main process
|
|
||||||
|
|
||||||
import "../common/system-ca"
|
|
||||||
import "../common/prometheus-providers"
|
|
||||||
import { app, dialog, protocol } from "electron"
|
|
||||||
import { PromiseIpc } from "electron-promise-ipc"
|
|
||||||
import path from "path"
|
|
||||||
import { format as formatUrl } from "url"
|
|
||||||
import logger from "./logger"
|
|
||||||
import initMenu from "./menu"
|
|
||||||
import * as proxy from "./proxy"
|
|
||||||
import { WindowManager } from "./window-manager";
|
|
||||||
import { clusterStore } from "../common/cluster-store"
|
|
||||||
import { tracker } from "./tracker"
|
|
||||||
import { ClusterManager } from "./cluster-manager";
|
|
||||||
import AppUpdater from "./app-updater"
|
|
||||||
import { shellSync } from "./shell-sync"
|
|
||||||
import { getFreePort } from "./port"
|
|
||||||
import { mangleProxyEnv } from "./proxy-env"
|
|
||||||
import { findMainWebContents } from "./webcontents"
|
|
||||||
import { registerStaticProtocol } from "../common/register-static";
|
|
||||||
import { isDevelopment, isMac } from "../common/vars";
|
|
||||||
|
|
||||||
mangleProxyEnv()
|
|
||||||
if (app.commandLine.getSwitchValue("proxy-server") !== "") {
|
|
||||||
process.env.HTTPS_PROXY = app.commandLine.getSwitchValue("proxy-server")
|
|
||||||
}
|
|
||||||
const promiseIpc = new PromiseIpc({ timeout: 2000 })
|
|
||||||
|
|
||||||
let windowManager: WindowManager = null;
|
|
||||||
let clusterManager: ClusterManager = null;
|
|
||||||
const vmURL = isDevelopment ? `http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}` : formatUrl({
|
|
||||||
pathname: path.join(__dirname, "index.html"),
|
|
||||||
protocol: "file",
|
|
||||||
slashes: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
await shellSync()
|
|
||||||
|
|
||||||
const updater = new AppUpdater()
|
|
||||||
updater.start();
|
|
||||||
|
|
||||||
tracker.event("app", "start");
|
|
||||||
|
|
||||||
registerStaticProtocol();
|
|
||||||
protocol.registerFileProtocol('store', (request, callback) => {
|
|
||||||
const url = request.url.substr(8)
|
|
||||||
callback(path.normalize(`${app.getPath("userData")}/${url}`))
|
|
||||||
}, (error) => {
|
|
||||||
if (error) console.error('Failed to register protocol')
|
|
||||||
})
|
|
||||||
|
|
||||||
let port: number = null
|
|
||||||
// find free port
|
|
||||||
try {
|
|
||||||
port = await getFreePort()
|
|
||||||
} catch (error) {
|
|
||||||
logger.error(error)
|
|
||||||
await dialog.showErrorBox("Lens Error", "Could not find a free port for the cluster proxy")
|
|
||||||
app.quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// create cluster manager
|
|
||||||
clusterManager = new ClusterManager(clusterStore.getAllClusterObjects(), port)
|
|
||||||
|
|
||||||
// run proxy
|
|
||||||
try {
|
|
||||||
proxy.listen(port, clusterManager)
|
|
||||||
} catch (error) {
|
|
||||||
logger.error(`Could not start proxy (127.0.0:${port}): ${error.message}`)
|
|
||||||
await dialog.showErrorBox("Lens Error", `Could not start proxy (127.0.0:${port}): ${error.message || "unknown error"}`)
|
|
||||||
app.quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// boot windowmanager
|
|
||||||
windowManager = new WindowManager();
|
|
||||||
windowManager.showMain(vmURL)
|
|
||||||
|
|
||||||
initMenu({
|
|
||||||
logoutHook: async () => {
|
|
||||||
// IPC send needs webContents as we're sending it to renderer
|
|
||||||
promiseIpc.send('logout', findMainWebContents(), {}).then((data: any) => {
|
|
||||||
logger.debug("logout IPC sent");
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showPreferencesHook: async () => {
|
|
||||||
// IPC send needs webContents as we're sending it to renderer
|
|
||||||
promiseIpc.send('navigate', findMainWebContents(), { name: 'preferences-page' }).then((data: any) => {
|
|
||||||
logger.debug("navigate: preferences IPC sent");
|
|
||||||
})
|
|
||||||
},
|
|
||||||
addClusterHook: async () => {
|
|
||||||
promiseIpc.send('navigate', findMainWebContents(), { name: "add-cluster-page" }).then((data: any) => {
|
|
||||||
logger.debug("navigate: add-cluster-page IPC sent");
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showWhatsNewHook: async () => {
|
|
||||||
promiseIpc.send('navigate', findMainWebContents(), { name: "whats-new-page" }).then((data: any) => {
|
|
||||||
logger.debug("navigate: whats-new-page IPC sent");
|
|
||||||
})
|
|
||||||
},
|
|
||||||
clusterSettingsHook: async () => {
|
|
||||||
promiseIpc.send('navigate', findMainWebContents(), { name: "cluster-settings-page" }).then((data: any) => {
|
|
||||||
logger.debug("navigate: cluster-settings-page IPC sent");
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}, promiseIpc)
|
|
||||||
}
|
|
||||||
|
|
||||||
app.on("ready", main)
|
|
||||||
app.on('window-all-closed', function () {
|
|
||||||
// On OS X it is common for applications and their menu bar
|
|
||||||
// to stay active until the user quits explicitly with Cmd + Q
|
|
||||||
if (!isMac) {
|
|
||||||
app.quit();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
windowManager = null
|
|
||||||
if (clusterManager) clusterManager.stop()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
app.on("activate", () => {
|
|
||||||
if (!windowManager) {
|
|
||||||
logger.debug("activate main window")
|
|
||||||
windowManager = new WindowManager(false)
|
|
||||||
windowManager.showMain(vmURL)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
app.on("will-quit", async (event) => {
|
|
||||||
event.preventDefault(); // To allow mixpanel sending to be executed
|
|
||||||
if (clusterManager) clusterManager.stop()
|
|
||||||
app.exit(0);
|
|
||||||
})
|
|
||||||
|
|
||||||
// todo: check auto-restart app in dev-mode
|
|
||||||
// if (isDevelopment) {
|
|
||||||
// require('electron-reloader')(module);
|
|
||||||
// }
|
|
||||||
@ -8,6 +8,7 @@ import logger from "./logger"
|
|||||||
import * as shell from "./node-shell-session"
|
import * as shell from "./node-shell-session"
|
||||||
import { ClusterManager } from "./cluster-manager"
|
import { ClusterManager } from "./cluster-manager"
|
||||||
import { Router } from "./router"
|
import { Router } from "./router"
|
||||||
|
import { apiPrefix } from "../common/vars";
|
||||||
|
|
||||||
export class LensProxy {
|
export class LensProxy {
|
||||||
public static readonly localShellSessions = true
|
public static readonly localShellSessions = true
|
||||||
@ -110,9 +111,10 @@ export class LensProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async getProxyTarget(req: http.IncomingMessage, contextHandler: ContextHandler): Promise<httpProxy.ServerOptions> {
|
protected async getProxyTarget(req: http.IncomingMessage, contextHandler: ContextHandler): Promise<httpProxy.ServerOptions> {
|
||||||
if (req.url.startsWith("/api-kube/")) {
|
const prefix = apiPrefix.KUBE_BASE;
|
||||||
|
if (req.url.startsWith(prefix)) {
|
||||||
delete req.headers.authorization
|
delete req.headers.authorization
|
||||||
req.url = req.url.replace("/api-kube", "")
|
req.url = req.url.replace(prefix, "")
|
||||||
const isWatchRequest = req.url.includes("watch=")
|
const isWatchRequest = req.url.includes("watch=")
|
||||||
return await contextHandler.getApiTarget(isWatchRequest)
|
return await contextHandler.getApiTarget(isWatchRequest)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { LensApiRequest } from "../router"
|
|||||||
import { LensApi } from "../lens-api"
|
import { LensApi } from "../lens-api"
|
||||||
import requestPromise from "request-promise-native"
|
import requestPromise from "request-promise-native"
|
||||||
import { PrometheusProviderRegistry, PrometheusProvider, PrometheusNodeQuery, PrometheusClusterQuery, PrometheusPodQuery, PrometheusPvcQuery, PrometheusIngressQuery, PrometheusQueryOpts} from "../prometheus/provider-registry"
|
import { PrometheusProviderRegistry, PrometheusProvider, PrometheusNodeQuery, PrometheusClusterQuery, PrometheusPodQuery, PrometheusPvcQuery, PrometheusIngressQuery, PrometheusQueryOpts} from "../prometheus/provider-registry"
|
||||||
|
import { apiPrefix } from "../../common/vars";
|
||||||
|
|
||||||
export type IMetricsQuery = string | string[] | {
|
export type IMetricsQuery = string | string[] | {
|
||||||
[metricName: string]: string;
|
[metricName: string]: string;
|
||||||
@ -12,7 +13,7 @@ class MetricsRoute extends LensApi {
|
|||||||
public async routeMetrics(request: LensApiRequest) {
|
public async routeMetrics(request: LensApiRequest) {
|
||||||
const { response, cluster} = request
|
const { response, cluster} = request
|
||||||
const query: IMetricsQuery = request.payload;
|
const query: IMetricsQuery = request.payload;
|
||||||
const serverUrl = `http://127.0.0.1:${cluster.port}/api-kube`
|
const serverUrl = `http://127.0.0.1:${cluster.port}${apiPrefix.KUBE_BASE}`
|
||||||
const headers = {
|
const headers = {
|
||||||
"Host": `${cluster.id}.localhost:${cluster.port}`,
|
"Host": `${cluster.id}.localhost:${cluster.port}`,
|
||||||
"Content-type": "application/json",
|
"Content-type": "application/json",
|
||||||
|
|||||||
@ -1,29 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="draggable-top" />
|
<div id="app_vue">
|
||||||
<div class="main-view" :class="{ 'menu-visible': isMenuVisible }">
|
<div id="lens-container" />
|
||||||
<main-menu v-if="isMenuVisible" />
|
<div class="draggable-top"/>
|
||||||
<router-view />
|
<div class="main-view" :class="{ 'menu-visible': isMenuVisible }">
|
||||||
|
<main-menu v-if="isMenuVisible"/>
|
||||||
|
<router-view/>
|
||||||
|
</div>
|
||||||
|
<bottom-bar v-if="isMenuVisible"/>
|
||||||
</div>
|
</div>
|
||||||
<bottom-bar v-if="isMenuVisible" />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import MainMenu from "@/_vue/components/MainMenu/MainMenu";
|
import MainMenu from "@/_vue/components/MainMenu/MainMenu";
|
||||||
import BottomBar from "@/_vue/components/BottomBar/BottomBar";
|
import BottomBar from "@/_vue/components/BottomBar/BottomBar";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Lens',
|
name: 'Lens',
|
||||||
components: {
|
components: {
|
||||||
BottomBar,
|
BottomBar,
|
||||||
MainMenu
|
MainMenu
|
||||||
},
|
},
|
||||||
computed:{
|
computed: {
|
||||||
isMenuVisible: function(){ return this.$store.getters.isMenuVisible }
|
isMenuVisible: function () { return this.$store.getters.isMenuVisible }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.draggable-top{
|
.draggable-top {
|
||||||
-webkit-app-region: drag;
|
-webkit-app-region: drag;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
|||||||
@ -25,18 +25,7 @@ pre {
|
|||||||
color: $lens-text-color-light;
|
color: $lens-text-color-light;
|
||||||
}
|
}
|
||||||
|
|
||||||
// react-app container (dashboard)
|
|
||||||
#app {
|
#app {
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 70px;
|
|
||||||
right: 0;
|
|
||||||
height: 100%;
|
|
||||||
z-index: 100;
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#app_vue {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
& > .main-view{
|
& > .main-view{
|
||||||
@ -161,7 +150,7 @@ h1, h2, h3, h4, h5, h6{
|
|||||||
|
|
||||||
// Force BS modals to use main app font etc.
|
// Force BS modals to use main app font etc.
|
||||||
.modal-open{
|
.modal-open{
|
||||||
@extend #app_vue
|
@extend #app
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover {
|
.popover {
|
||||||
@ -205,3 +194,13 @@ h1, h2, h3, h4, h5, h6{
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#lens-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 70px;
|
||||||
|
right: 0;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 100;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|||||||
@ -89,7 +89,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
#app_vue > .main-view > .content {
|
#app > .main-view > .content {
|
||||||
left: 70px;
|
left: 70px;
|
||||||
right: 70px;
|
right: 70px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,7 +98,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
#app_vue > .main-view > .content {
|
#app > .main-view > .content {
|
||||||
left: 70px;
|
left: 70px;
|
||||||
right: 70px;
|
right: 70px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -225,7 +225,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
#app_vue > .main-view > .content {
|
#app > .main-view > .content {
|
||||||
left: 70px;
|
left: 70px;
|
||||||
}
|
}
|
||||||
.lens-preferences {
|
.lens-preferences {
|
||||||
|
|||||||
@ -98,7 +98,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
#app_vue > .main-view > .content {
|
#app > .main-view > .content {
|
||||||
left: 70px;
|
left: 70px;
|
||||||
right: 70px;
|
right: 70px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import "../../common/system-ca"
|
||||||
import "./assets/css/app.scss"
|
import "./assets/css/app.scss"
|
||||||
import "prismjs";
|
import "prismjs";
|
||||||
import "prismjs/components/prism-yaml"
|
import "prismjs/components/prism-yaml"
|
||||||
@ -29,19 +30,19 @@ Vue.mixin({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// run
|
// any initialization we want to do for app state
|
||||||
setTimeout(main, 250);
|
setTimeout(() => {
|
||||||
|
store.dispatch('init', ).catch((error) => {
|
||||||
export async function main() {
|
console.error(error)
|
||||||
try {
|
}).finally(() => {
|
||||||
await store.dispatch('init');
|
/* eslint-disable no-new */
|
||||||
|
console.log("start vue")
|
||||||
new Vue({
|
new Vue({
|
||||||
components: {App},
|
components: { App },
|
||||||
|
persist,
|
||||||
store,
|
store,
|
||||||
router,
|
router,
|
||||||
template: '<App/>'
|
template: '<App/>'
|
||||||
}).$mount('#app_vue')
|
}).$mount('#app')
|
||||||
} catch (err) {
|
})
|
||||||
console.error(err)
|
}, 0)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -166,7 +166,7 @@ const actions: ActionTree<ClusterState, any> = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
attachWebview({commit}, lens: LensWebview) {
|
attachWebview({commit}, lens: LensWebview) {
|
||||||
const container: any = document.getElementById("app");
|
const container: any = document.getElementById("lens-container");
|
||||||
if (!container || !lens.webview) {
|
if (!container || !lens.webview) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -190,7 +190,7 @@ const actions: ActionTree<ClusterState, any> = {
|
|||||||
promiseIpc.send("enableClusterSettingsMenuItem", lens.id)
|
promiseIpc.send("enableClusterSettingsMenuItem", lens.id)
|
||||||
},
|
},
|
||||||
detachWebview({commit}, lens: LensWebview) {
|
detachWebview({commit}, lens: LensWebview) {
|
||||||
const container: any = document.getElementById("app");
|
const container: any = document.getElementById("lens-container");
|
||||||
if (!container) { return }
|
if (!container) { return }
|
||||||
container.childNodes.forEach((child: any) => {
|
container.childNodes.forEach((child: any) => {
|
||||||
if (child === lens.webview) {
|
if (child === lens.webview) {
|
||||||
@ -203,7 +203,7 @@ const actions: ActionTree<ClusterState, any> = {
|
|||||||
promiseIpc.send("disableClusterSettingsMenuItem")
|
promiseIpc.send("disableClusterSettingsMenuItem")
|
||||||
},
|
},
|
||||||
hideWebviews({commit}) {
|
hideWebviews({commit}) {
|
||||||
const container: any = document.getElementById("app");
|
const container: any = document.getElementById("lens-container");
|
||||||
if (!container) { return }
|
if (!container) { return }
|
||||||
container.style = "display: none;"
|
container.style = "display: none;"
|
||||||
container.childNodes.forEach((child: any) => {
|
container.childNodes.forEach((child: any) => {
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import "../../common/system-ca"
|
|
||||||
import "./app.scss";
|
import "./app.scss";
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|||||||
@ -7,15 +7,11 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
We are using node <script>document.write(process.versions.node)</script>,
|
|
||||||
Chrome <script>document.write(process.versions.chrome)</script>,
|
|
||||||
and Electron <script>document.write(process.versions.electron)</script>.
|
|
||||||
|
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<div id="app_vue"></div>
|
|
||||||
|
|
||||||
<script src="dll.js"></script>
|
<!--<div id="app_vue"></div>-->
|
||||||
<script src="renderer_vue.js"></script>
|
<!--<script src="dll.js"></script>-->
|
||||||
|
<!--<script src="renderer_vue.js"></script>-->
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@ -7,6 +7,7 @@ export default function (): webpack.Configuration {
|
|||||||
return {
|
return {
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
target: "electron-main",
|
target: "electron-main",
|
||||||
|
devtool: "source-map",
|
||||||
mode: isProduction ? "production" : "development",
|
mode: isProduction ? "production" : "development",
|
||||||
cache: isDevelopment,
|
cache: isDevelopment,
|
||||||
entry: {
|
entry: {
|
||||||
@ -18,12 +19,18 @@ export default function (): webpack.Configuration {
|
|||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.json', '.js', '.ts']
|
extensions: ['.json', '.js', '.ts']
|
||||||
},
|
},
|
||||||
externals: [
|
node: {
|
||||||
"@kubernetes/client-node",
|
// webpack modifies node internals by default, keep as is for main-process
|
||||||
"handlebars",
|
__dirname: false,
|
||||||
"node-pty",
|
__filename: false,
|
||||||
"ws",
|
},
|
||||||
],
|
// fixme: hiding warnings during compilation, but creates runtime error
|
||||||
|
// externals: [
|
||||||
|
// "@kubernetes/client-node",
|
||||||
|
// "handlebars",
|
||||||
|
// "node-pty",
|
||||||
|
// "ws",
|
||||||
|
// ],
|
||||||
module: {
|
module: {
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
@ -38,7 +45,7 @@ export default function (): webpack.Configuration {
|
|||||||
options: {
|
options: {
|
||||||
transpileOnly: true,
|
transpileOnly: true,
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import TerserPlugin from "terser-webpack-plugin";
|
|||||||
import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin"
|
import ForkTsCheckerPlugin from "fork-ts-checker-webpack-plugin"
|
||||||
import { VueLoaderPlugin } from "vue-loader"
|
import { VueLoaderPlugin } from "vue-loader"
|
||||||
import { htmlTemplate, isDevelopment, isProduction, outDir, rendererDir, sassCommonVars } from "./src/common/vars";
|
import { htmlTemplate, isDevelopment, isProduction, outDir, rendererDir, sassCommonVars } from "./src/common/vars";
|
||||||
import { libraryTarget, manifestPath } from "./webpack.dll";
|
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
webpackConfigReact,
|
webpackConfigReact,
|
||||||
@ -17,8 +16,8 @@ export function webpackConfigReact(): webpack.Configuration {
|
|||||||
return {
|
return {
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
target: "electron-renderer",
|
target: "electron-renderer",
|
||||||
|
devtool: "source-map",
|
||||||
mode: isProduction ? "production" : "development",
|
mode: isProduction ? "production" : "development",
|
||||||
devtool: isProduction ? "source-map" : "cheap-module-eval-source-map",
|
|
||||||
cache: isDevelopment,
|
cache: isDevelopment,
|
||||||
entry: {
|
entry: {
|
||||||
renderer: path.resolve(rendererDir, "components/app.tsx"),
|
renderer: path.resolve(rendererDir, "components/app.tsx"),
|
||||||
@ -119,16 +118,12 @@ export function webpackConfigReact(): webpack.Configuration {
|
|||||||
// new ForkTsCheckerPlugin(),
|
// new ForkTsCheckerPlugin(),
|
||||||
|
|
||||||
// todo: check if this actually works in mode=production files
|
// todo: check if this actually works in mode=production files
|
||||||
new webpack.DllReferencePlugin({
|
// new webpack.DllReferencePlugin({
|
||||||
context: process.cwd(),
|
// context: process.cwd(),
|
||||||
manifest: manifestPath,
|
// manifest: manifestPath,
|
||||||
sourceType: libraryTarget,
|
// sourceType: libraryTarget,
|
||||||
}),
|
// }),
|
||||||
|
|
||||||
new HtmlWebpackPlugin({
|
|
||||||
template: htmlTemplate,
|
|
||||||
inject: true,
|
|
||||||
}),
|
|
||||||
new MiniCssExtractPlugin({
|
new MiniCssExtractPlugin({
|
||||||
filename: "[name].css",
|
filename: "[name].css",
|
||||||
}),
|
}),
|
||||||
@ -188,6 +183,11 @@ export function webpackConfigVue(): webpack.Configuration {
|
|||||||
config.plugins = [
|
config.plugins = [
|
||||||
new VueLoaderPlugin(),
|
new VueLoaderPlugin(),
|
||||||
new ForkTsCheckerPlugin(),
|
new ForkTsCheckerPlugin(),
|
||||||
|
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: htmlTemplate,
|
||||||
|
inject: true,
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
|
|||||||
@ -390,7 +390,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.10.1"
|
"@babel/helper-plugin-utils" "^7.10.1"
|
||||||
|
|
||||||
"@babel/plugin-syntax-dynamic-import@^7.8.0", "@babel/plugin-syntax-dynamic-import@^7.8.3":
|
"@babel/plugin-syntax-dynamic-import@^7.2.0", "@babel/plugin-syntax-dynamic-import@^7.8.0":
|
||||||
version "7.8.3"
|
version "7.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
|
||||||
integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
|
integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
|
||||||
@ -716,7 +716,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/helper-plugin-utils" "^7.10.1"
|
"@babel/helper-plugin-utils" "^7.10.1"
|
||||||
|
|
||||||
"@babel/plugin-transform-runtime@^7.10.1":
|
"@babel/plugin-transform-runtime@^7.6.2":
|
||||||
version "7.10.1"
|
version "7.10.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.1.tgz#fd1887f749637fb2ed86dc278e79eb41df37f4b1"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.10.1.tgz#fd1887f749637fb2ed86dc278e79eb41df37f4b1"
|
||||||
integrity sha512-4w2tcglDVEwXJ5qxsY++DgWQdNJcCCsPxfT34wCUwIf2E7dI7pMpH8JczkMBbgBTNzBX62SZlNJ9H+De6Zebaw==
|
integrity sha512-4w2tcglDVEwXJ5qxsY++DgWQdNJcCCsPxfT34wCUwIf2E7dI7pMpH8JczkMBbgBTNzBX62SZlNJ9H+De6Zebaw==
|
||||||
@ -889,7 +889,7 @@
|
|||||||
"@babel/helper-plugin-utils" "^7.10.1"
|
"@babel/helper-plugin-utils" "^7.10.1"
|
||||||
"@babel/plugin-transform-typescript" "^7.10.1"
|
"@babel/plugin-transform-typescript" "^7.10.1"
|
||||||
|
|
||||||
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6":
|
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.6":
|
||||||
version "7.10.2"
|
version "7.10.2"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.2.tgz#d103f21f2602497d38348a32e008637d506db839"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.2.tgz#d103f21f2602497d38348a32e008637d506db839"
|
||||||
integrity sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg==
|
integrity sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg==
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user