Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen committed 2020-06-24 08:59:11 +03:00
1 parent b95586df87
commit 6852388145
28 files changed
+642 -204

No files matched your search

+8 -3
View File
@@ -1,9 +1,14 @@
import { isMac, isWindows } from "./vars";
import winca from "win-ca"
import macca from "mac-ca"
import logger from "../main/logger"
if (isMac) {
// fixme: mac-ca import error
// require("mac-ca");
for (const crt of macca.all()) {
const attributes = crt.issuer?.attributes?.map((a: any) => `${a.name}=${a.value}`)
logger.debug("Using host CA: " + attributes.join(","))
}
}
if (isWindows) {
require("win-ca").inject("+") // see: https://github.com/ukoloff/win-ca#caveats
winca.inject("+") // see: https://github.com/ukoloff/win-ca#caveats
}
+4
View File
@@ -3,3 +3,7 @@ import packageInfo from "../../../package.json"
export function getAppVersion(): string {
return packageInfo.version;
}
export function getBundledKubectlVersion(): string {
return packageInfo.config.bundledKubectlVersion;
}
+3 -2
View File
@@ -41,7 +41,6 @@ export class KubeAuthProxy {
}
}
})
configWatcher.on("error", () => {})
const clusterUrl = url.parse(this.cluster.apiUrl)
let args = [
"proxy",
@@ -57,7 +56,9 @@ export class KubeAuthProxy {
})
this.proxyProcess.on("exit", (code) => {
logger.error(`proxy ${this.cluster.contextName} exited with code ${code}`)
this.sendIpcLogMessage( `proxy exited with code ${code}`, "stderr").catch((_) => {})
this.sendIpcLogMessage( `proxy exited with code ${code}`, "stderr").catch((err: Error) => {
logger.debug("failed to send IPC log message: " + err.message)
})
this.proxyProcess = null
configWatcher.close()
})
+5 -4
View File
@@ -9,8 +9,9 @@ import { globalRequestOpts } from "../common/request"
import * as lockFile from "proper-lockfile"
import { helmCli } from "./helm-cli"
import { userStore } from "../common/user-store"
import { getBundledKubectlVersion} from "../common/utils/app-version"
const bundledVersion = require("../../package.json").config.bundledKubectlVersion
const bundledVersion = getBundledKubectlVersion()
const kubectlMap: Map<string, string> = new Map([
["1.7", "1.8.15"],
["1.8", "1.9.10"],
@@ -194,16 +195,16 @@ export class Kubectl {
const file = fs.createWriteStream(this.path)
stream.on("complete", () => {
logger.debug("kubectl binary download finished")
file.end(() => {})
file.end()
})
stream.on("error", (error) => {
logger.error(error)
fs.unlink(this.path, () => {})
fs.unlink(this.path, null)
reject(error)
})
file.on("close", () => {
logger.debug("kubectl binary download closed")
fs.chmod(this.path, 0o755, () => {})
fs.chmod(this.path, 0o755, null)
resolve()
})
stream.pipe(file)
+3 -6
View File
@@ -159,21 +159,18 @@ export class LensBinary {
stream.on("complete", () => {
logger.info(`Download of ${this.originalBinaryName} finished`)
file.end(() => {
})
file.end()
})
stream.on("error", (error) => {
logger.error(error)
fs.unlink(binaryPath, () => {
})
fs.unlink(binaryPath, null)
throw(error)
})
return new Promise((resolve, reject) => {
file.on("close", () => {
logger.debug(`${this.originalBinaryName} binary download closed`)
if (!this.tarPath) fs.chmod(binaryPath, 0o755, () => {
})
if (!this.tarPath) fs.chmod(binaryPath, 0o755, null)
resolve()
})
stream.pipe(file)
+6 -6
View File
@@ -78,11 +78,11 @@ export default function initMenu(opts: MenuOptions, promiseIpc: any) {
label: 'Add Cluster...',
click: opts.addClusterHook,
},
{
label: 'Cluster Settings',
click: opts.clusterSettingsHook,
enabled: false
}
{
label: 'Cluster Settings',
click: opts.clusterSettingsHook,
enabled: false
}
]
}
}
@@ -215,4 +215,4 @@ export default function initMenu(opts: MenuOptions, promiseIpc: any) {
promiseIpc.on("disableClusterSettingsMenuItem", () => {
setClusterSettingsEnabled(false)
});
};
}
+4 -4
View File
@@ -1,12 +1,12 @@
<template>
<div id="app">
<div id="lens-container" />
<div class="draggable-top"/>
<div class="draggable-top" />
<div class="main-view" :class="{ 'menu-visible': isMenuVisible }">
<main-menu v-if="isMenuVisible"/>
<router-view/>
<main-menu v-if="isMenuVisible" />
<router-view />
</div>
<bottom-bar v-if="isMenuVisible"/>
<bottom-bar v-if="isMenuVisible" />
</div>
</template>
@@ -6,7 +6,7 @@
:cluster="cluster"
/>
</draggable>
<AddClusterMenuItem/>
<AddClusterMenuItem />
<b-tooltip v-if="clusters.length === 0" show target="add-cluster" placement="rightbottom">
<p class="text-left">
This is the quick launch menu.
@@ -19,57 +19,57 @@
</template>
<script>
import ClusterMenuItem from "@/_vue/components/MainMenu/ClusterMenuItem";
import AddClusterMenuItem from "@/_vue/components/MainMenu/AddClusterMenuItem";
import draggable from 'vuedraggable'
import { clusterStore } from "../../../../common/cluster-store"
import { isMac } from "../../../../common/vars"
import ClusterMenuItem from "@/_vue/components/MainMenu/ClusterMenuItem";
import AddClusterMenuItem from "@/_vue/components/MainMenu/AddClusterMenuItem";
import draggable from 'vuedraggable'
import { clusterStore } from "../../../../common/cluster-store"
import { isMac } from "../../../../common/vars"
const {remote} = require('electron')
const {Menu, MenuItem} = remote
const {remote} = require('electron')
const {Menu, MenuItem} = remote
export default {
name: "MainMenu",
components: {
ClusterMenuItem,
AddClusterMenuItem,
draggable
},
data() {
return {
computedPaddingTop: "15px"
}
},
computed: {
clusters: {
get: function () {
return this.$store.getters.clusters;
},
set: function (clusters) {
this.$store.commit("updateClusters", clusters);
clusterStore.storeClusters(clusters);
}
}
},
methods: {
isActive: function (id) {
return id === this.$route.params.id;
export default {
name: "MainMenu",
components: {
ClusterMenuItem,
AddClusterMenuItem,
draggable
},
data() {
return {
computedPaddingTop: "15px"
}
},
computed: {
clusters: {
get: function () {
return this.$store.getters.clusters;
},
addCluster: async function () {
this.$router.push({
name: "add-cluster-page",
params: {
id: "new"
},
}).catch(err => {})
}
},
mounted: function () {
if (isMac) {
this.computedPaddingTop = "25px";
set: function (clusters) {
this.$store.commit("updateClusters", clusters);
clusterStore.storeClusters(clusters);
}
}
},
methods: {
isActive: function (id) {
return id === this.$route.params.id;
},
addCluster: async function () {
this.$router.push({
name: "add-cluster-page",
params: {
id: "new"
},
}).catch(err => {})
}
},
mounted: function () {
if (isMac) {
this.computedPaddingTop = "25px";
}
}
}
</script>
<style scoped lang="scss">
+4 -4
View File
@@ -25,10 +25,10 @@ export const apiResourceApplier = new KubeJsonApi({
// Common handler for HTTP api errors
function onApiError(error: JsonApiErrorParsed, res: Response) {
switch (res.status) {
case 403:
error.isUsedForNotification = true;
Notifications.error(error);
break;
case 403:
error.isUsedForNotification = true;
Notifications.error(error);
break;
}
}
+22 -22
View File
@@ -50,29 +50,29 @@ export class KubeApi<T extends KubeObject = any> {
if (namespaced) {
switch (right.length) {
case 1:
case 1:
name = right[0];
// fallthroughcase 0:
resource = "namespaces"; // special case this due to `split` removing namespaces
resource = "namespaces"; // special case this due to `split` removing namespaces
break;
default:
[namespace, resource, name] = right;
break;
break;
default:
[namespace, resource, name] = right;
break;
}
apiVersion = left.pop();
apiGroup = left.join("/");
} else {
switch (left.length) {
case 2:
resource = left.pop();
case 2:
resource = left.pop();
// fallthroughcase 1:
apiVersion = left.pop();
apiGroup = "";
break;
default:
/**
apiVersion = left.pop();
apiGroup = "";
break;
default:
/**
* Given that
* - `apiVersion` is `GROUP/VERSION` and
* - `VERSION` is `DNS_LABEL` which is /^[a-z0-9]((-[a-z0-9])|[a-z0-9])*$/i
@@ -88,15 +88,15 @@ export class KubeApi<T extends KubeObject = any> {
* 3. otherwise assume apiVersion <- left[0]
* 4. always resource, name <- left[(0 or 1)+1..]
*/
if (left[0].includes('.') || left[1].match(/^v[0-9]/)) {
[apiGroup, apiVersion] = left;
resource = left.slice(2).join("/")
} else {
apiGroup = "";
apiVersion = left[0];
[resource, name] = left.slice(1)
}
break;
if (left[0].includes('.') || left[1].match(/^v[0-9]/)) {
[apiGroup, apiVersion] = left;
resource = left.slice(2).join("/")
} else {
apiGroup = "";
apiVersion = left[0];
[resource, name] = left.slice(1)
}
break;
}
}
+2 -1
View File
@@ -48,7 +48,8 @@ export class TerminalApi extends WebSocketApi {
}
async getUrl(token: string) {
var { hostname, protocol, port } = location;
const { hostname, protocol } = location;
let { port } = location;
const prefix = apiPrefix.TERMINAL;
const { id, node } = this.options;
const wss = `ws${protocol === "https:" ? "s" : ""}://`;
@@ -28,7 +28,7 @@ export class EndpointDetails extends React.Component<Props> {
{
endpoint.getEndpointSubsets().map((subset) => {
return(
<EndpointSubsetList subset={subset} endpoint={endpoint}/>
<EndpointSubsetList subset={subset} endpoint={endpoint}/>
)
})
}
@@ -71,9 +71,9 @@ export class EndpointSubsetList extends React.Component<Props> {
<TableCell className="name">{address.hostname}</TableCell>
<TableCell className="target">
{ address.targetRef && (
<Link to={getDetailsUrl(lookupApiLink(address.getTargetRef(), endpoint))}>
{address.targetRef.name}
</Link>
<Link to={getDetailsUrl(lookupApiLink(address.getTargetRef(), endpoint))}>
{address.targetRef.name}
</Link>
)}
</TableCell>
</TableRow>
@@ -90,45 +90,45 @@ export class EndpointSubsetList extends React.Component<Props> {
return(
<div className="EndpointSubsetList flex column">
{addresses.length > 0 && (
<div>
<div className="title flex gaps"><Trans>Addresses</Trans></div>
<Table
items={addresses}
selectable={false}
virtual={addressesVirtual}
scrollable={false}
getTableRow={this.getAddressTableRow}
className="box grow"
>
<TableHead>
<TableCell className="ip">IP</TableCell>
<TableCell className="host"><Trans>Hostname</Trans></TableCell>
<TableCell className="target">Target</TableCell>
</TableHead>
{ !addressesVirtual && addresses.map(address => this.getAddressTableRow(address.getId())) }
</Table>
</div>
<div>
<div className="title flex gaps"><Trans>Addresses</Trans></div>
<Table
items={addresses}
selectable={false}
virtual={addressesVirtual}
scrollable={false}
getTableRow={this.getAddressTableRow}
className="box grow"
>
<TableHead>
<TableCell className="ip">IP</TableCell>
<TableCell className="host"><Trans>Hostname</Trans></TableCell>
<TableCell className="target">Target</TableCell>
</TableHead>
{ !addressesVirtual && addresses.map(address => this.getAddressTableRow(address.getId())) }
</Table>
</div>
)}
{notReadyAddresses.length > 0 && (
<div>
<div className="title flex gaps"><Trans>Not Ready Addresses</Trans></div>
<Table
items={notReadyAddresses}
selectable
virtual={notReadyAddressesVirtual}
scrollable={false}
getTableRow={this.getNotReadyAddressTableRow}
className="box grow"
>
<TableHead>
<TableCell className="ip">IP</TableCell>
<TableCell className="host"><Trans>Hostname</Trans></TableCell>
<TableCell className="target">Target</TableCell>
</TableHead>
{ !notReadyAddressesVirtual && notReadyAddresses.map(address => this.getNotReadyAddressTableRow(address.getId())) }
</Table>
</div>
<div>
<div className="title flex gaps"><Trans>Not Ready Addresses</Trans></div>
<Table
items={notReadyAddresses}
selectable
virtual={notReadyAddressesVirtual}
scrollable={false}
getTableRow={this.getNotReadyAddressTableRow}
className="box grow"
>
<TableHead>
<TableCell className="ip">IP</TableCell>
<TableCell className="host"><Trans>Hostname</Trans></TableCell>
<TableCell className="target">Target</TableCell>
</TableHead>
{ !notReadyAddressesVirtual && notReadyAddresses.map(address => this.getNotReadyAddressTableRow(address.getId())) }
</Table>
</div>
)}
<div className="title flex gaps"><Trans>Ports</Trans></div>
@@ -23,25 +23,25 @@ export class ServiceDetailsEndpoint extends React.Component<Props> {
return null
}
return (
<div className="EndpointList flex column">
<div className="EndpointList flex column">
<Table
selectable
virtual={false}
scrollable={false}
className="box grow"
selectable
virtual={false}
scrollable={false}
className="box grow"
>
<TableHead>
<TableCell className="name" ><Trans>Name</Trans></TableCell>
<TableCell className="endpoints"><Trans>Endpoints</Trans></TableCell>
</TableHead>
<TableRow
key={endpoint.getId()}
nowrap
onClick={prevDefault(() => showDetails(endpoint.selfLink, false))}
>
<TableCell className="name">{endpoint.getName()}</TableCell>
<TableCell className="endpoints">{ endpoint.toString()}</TableCell>
</TableRow>
<TableHead>
<TableCell className="name" ><Trans>Name</Trans></TableCell>
<TableCell className="endpoints"><Trans>Endpoints</Trans></TableCell>
</TableHead>
<TableRow
key={endpoint.getId()}
nowrap
onClick={prevDefault(() => showDetails(endpoint.selfLink, false))}
>
<TableCell className="name">{endpoint.getName()}</TableCell>
<TableCell className="endpoints">{ endpoint.toString()}</TableCell>
</TableRow>
</Table>
</div>
)
@@ -125,14 +125,14 @@ const SecretKey = (props: SecretKeyProps) => {
}
return (
<>
<>
secretKeyRef({name}.{key})&nbsp;
<Icon
className={cssNames("secret-button", { loading })}
material="visibility"
tooltip={<Trans>Show</Trans>}
onClick={showKey}
/>
</>
<Icon
className={cssNames("secret-button", { loading })}
material="visibility"
tooltip={<Trans>Show</Trans>}
onClick={showKey}
/>
</>
)
}
@@ -174,28 +174,28 @@ export class PodDetails extends React.Component<Props> {
</DrawerItem>
{ type == "configMap" && (
<div>
{configMap && (
<DrawerItem name={<Trans>Name</Trans>}>
<Link
to={getDetailsUrl(configMapApi.getUrl({
name: configMap,
namespace: pod.getNs(),
}))}>{configMap}
</Link>
</DrawerItem>
)}
{configMap && (
<DrawerItem name={<Trans>Name</Trans>}>
<Link
to={getDetailsUrl(configMapApi.getUrl({
name: configMap,
namespace: pod.getNs(),
}))}>{configMap}
</Link>
</DrawerItem>
)}
</div>
)}
{ type === "emptyDir" && (
<div>
{ volume.emptyDir.medium && (
<DrawerItem name={<Trans>Medium</Trans>}>
{volume.emptyDir.medium}
</DrawerItem>
<DrawerItem name={<Trans>Medium</Trans>}>
{volume.emptyDir.medium}
</DrawerItem>
)}
{ volume.emptyDir.sizeLimit && (
<DrawerItem name={<Trans>Size Limit</Trans>}>
{volume.emptyDir.sizeLimit}
{volume.emptyDir.sizeLimit}
</DrawerItem>
)}
</div>
@@ -81,7 +81,7 @@ export class Workloads extends React.Component<Props> {
})
}
return routes;
};
}
render() {
const tabRoutes = Workloads.tabRoutes;
@@ -48,10 +48,10 @@ export class AceEditor extends React.Component<Props, State> {
get theme() {
switch (themeStore.activeTheme.type) {
case "light":
return "dreamweaver"
case "dark":
return "terminal";
case "light":
return "dreamweaver"
case "dark":
return "terminal";
}
}
+1 -1
View File
@@ -44,7 +44,7 @@ export class App extends React.Component {
await configStore.init();
await Terminal.preloadFonts();
render(<App/>, App.rootElem);
};
}
render() {
const homeUrl = isAllowedResource(["events", "nodes", "pods"]) ? clusterURL() : workloadsURL();
+3 -3
View File
@@ -21,8 +21,8 @@ export class Terminal {
}
static async preloadFonts(){
var fontPath = require("../fonts/roboto-mono-nerd.ttf").default;
var fontFace = new FontFace("RobotoMono", `url(${fontPath})`);
const fontPath = require("../fonts/roboto-mono-nerd.ttf").default; // eslint-disable-line @typescript-eslint/no-var-requires
const fontFace = new FontFace("RobotoMono", `url(${fontPath})`);
await fontFace.load();
document.fonts.add(fontFace);
}
@@ -193,4 +193,4 @@ export class Terminal {
}
}
Terminal.init();
Terminal.init();
+3 -3
View File
@@ -243,9 +243,9 @@ export class Input extends React.Component<InputProps, State> {
}
render() {
var { multiLine, showValidationLine, validators, theme, maxRows, iconLeft, iconRight, children, ...inputProps } = this.props;
var { className, maxLength, rows, disabled } = this.props;
var { focused, dirty, valid, validating, errors } = this.state;
const { multiLine, showValidationLine, validators, theme, maxRows, children, maxLength, rows, disabled, ...inputProps } = this.props;
let { className, iconLeft, iconRight } = this.props;
const { focused, dirty, valid, validating, errors } = this.state;
className = cssNames("Input", className, {
[`theme ${theme}`]: theme,
+2 -2
View File
@@ -4,7 +4,7 @@ import { setupI18n } from "@lingui/core";
import orderBy from "lodash/orderBy"
import { autobind, createStorage } from "./utils";
const plurals: Record<string, Function> = require('make-plural/plurals');
const plurals: Record<string, Function> = require('make-plural/plurals'); // eslint-disable-line @typescript-eslint/no-var-requires
export interface ILanguage {
code: string;
@@ -42,7 +42,7 @@ export class LocalizationStore {
}
async setLocale(locale: string) {
const catalog = require(`@lingui/loader!../../locales/${locale}/messages.po`);
const catalog = require(`@lingui/loader!../../locales/${locale}/messages.po`); // eslint-disable-line @typescript-eslint/no-var-requires
_i18n.loadLocaleData(locale, { plurals: plurals[locale] });
_i18n.load(locale, catalog.messages);
+2 -2
View File
@@ -170,7 +170,7 @@ export class ThemeStore {
return this.themes.get(themeId);
}
try {
const theme: ITheme = require(
const theme: ITheme = require( // eslint-disable-line @typescript-eslint/no-var-requires
/* webpackMode: "lazy", webpackChunkName: "theme/[request]" */
`./themes/${themeId}.json`
);
@@ -195,4 +195,4 @@ export class ThemeStore {
}
}
export const themeStore = new ThemeStore();
export const themeStore = new ThemeStore();