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

Merge pull request #1966 from lensapp/release/v4.0.7

Release v4.0.7
This commit is contained in:
Jari Kolehmainen 2021-01-20 10:51:31 +02:00 committed by GitHub
commit a9d2a9ea0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 91 additions and 41 deletions

View File

@ -2,7 +2,7 @@
"name": "kontena-lens",
"productName": "Lens",
"description": "Lens - The Kubernetes IDE",
"version": "4.0.6",
"version": "4.0.7",
"main": "static/build/main.js",
"copyright": "© 2020, Mirantis, Inc.",
"license": "MIT",

View File

@ -36,6 +36,13 @@ describe("workspace store tests", () => {
expect(ws.getById(WorkspaceStore.defaultId)).not.toBe(null);
});
it("default workspace should be enabled", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();
expect(ws.workspaces.size).toBe(1);
expect(ws.getById(WorkspaceStore.defaultId).enabled).toBe(true);
});
it("cannot remove the default workspace", () => {
const ws = WorkspaceStore.getInstance<WorkspaceStore>();

View File

@ -58,14 +58,7 @@ export class Workspace implements WorkspaceModel, WorkspaceState {
* @observable
*/
@observable ownerRef?: string;
/**
* Is workspace enabled
*
* Workspaces that don't have ownerRef will be enabled by default. Workspaces with ownerRef need to explicitly enable a workspace.
*
* @observable
*/
@observable enabled: boolean;
/**
* Last active cluster id
*
@ -73,6 +66,9 @@ export class Workspace implements WorkspaceModel, WorkspaceState {
*/
@observable lastActiveClusterId?: ClusterId;
@observable private _enabled: boolean;
constructor(data: WorkspaceModel) {
Object.assign(this, data);
@ -83,6 +79,21 @@ export class Workspace implements WorkspaceModel, WorkspaceState {
}
}
/**
* Is workspace enabled
*
* Workspaces that don't have ownerRef will be enabled by default. Workspaces with ownerRef need to explicitly enable a workspace.
*
* @observable
*/
get enabled(): boolean {
return !this.isManaged || this._enabled;
}
set enabled(enabled: boolean) {
this._enabled = enabled;
}
/**
* Is workspace managed by an extension
*/
@ -134,10 +145,18 @@ export class WorkspaceStore extends BaseStore<WorkspaceStoreModel> {
static readonly defaultId: WorkspaceId = "default";
private static stateRequestChannel = "workspace:states";
@observable currentWorkspaceId = WorkspaceStore.defaultId;
@observable workspaces = observable.map<WorkspaceId, Workspace>();
private constructor() {
super({
configName: "lens-workspace-store",
});
this.workspaces.set(WorkspaceStore.defaultId, new Workspace({
id: WorkspaceStore.defaultId,
name: "default"
}));
}
async load() {
@ -186,15 +205,6 @@ export class WorkspaceStore extends BaseStore<WorkspaceStoreModel> {
ipcRenderer.removeAllListeners("workspace:state");
}
@observable currentWorkspaceId = WorkspaceStore.defaultId;
@observable workspaces = observable.map<WorkspaceId, Workspace>({
[WorkspaceStore.defaultId]: new Workspace({
id: WorkspaceStore.defaultId,
name: "default"
})
});
@computed get currentWorkspace(): Workspace {
return this.getById(this.currentWorkspaceId);
}

View File

@ -14,7 +14,7 @@ export class ClusterManager extends Singleton {
// auto-init clusters
autorun(() => {
clusterStore.enabledClustersList.forEach(cluster => {
if (!cluster.initialized) {
if (!cluster.initialized && !cluster.initializing) {
logger.info(`[CLUSTER-MANAGER]: init cluster`, cluster.getMeta());
cluster.init(port);
}

View File

@ -84,6 +84,14 @@ export class Cluster implements ClusterModel, ClusterState {
whenInitialized = when(() => this.initialized);
whenReady = when(() => this.ready);
/**
* Is cluster object initializinng on-going
*
* @observable
*/
@observable initializing = false;
/**
* Is cluster object initialized
*
@ -273,6 +281,7 @@ export class Cluster implements ClusterModel, ClusterState {
*/
@action async init(port: number) {
try {
this.initializing = true;
this.contextHandler = new ContextHandler(this);
this.kubeconfigManager = await KubeconfigManager.create(this, this.contextHandler, port);
this.kubeProxyUrl = `http://localhost:${port}${apiKubePrefix}`;
@ -287,6 +296,8 @@ export class Cluster implements ClusterModel, ClusterState {
id: this.id,
error: err,
});
} finally {
this.initializing = false;
}
}

View File

@ -75,8 +75,8 @@ export class PrometheusLens implements PrometheusProvider {
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
return {
bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
bytesSentSuccess: bytesSent(opts.ingress, "^2\\\\d*"),
bytesSentFailure: bytesSent(opts.ingress, "^5\\\\d*"),
requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
};

View File

@ -85,8 +85,8 @@ export class PrometheusOperator implements PrometheusProvider {
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
return {
bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
bytesSentSuccess: bytesSent(opts.ingress, "^2\\\\d*"),
bytesSentFailure: bytesSent(opts.ingress, "^5\\\\d*"),
requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
};

View File

@ -75,8 +75,8 @@ export class PrometheusStacklight implements PrometheusProvider {
`sum(rate(nginx_ingress_controller_bytes_sent_sum{ingress="${ingress}", status=~"${statuses}"}[${this.rateAccuracy}])) by (ingress)`;
return {
bytesSentSuccess: bytesSent(opts.igress, "^2\\\\d*"),
bytesSentFailure: bytesSent(opts.ingres, "^5\\\\d*"),
bytesSentSuccess: bytesSent(opts.ingress, "^2\\\\d*"),
bytesSentFailure: bytesSent(opts.ingress, "^5\\\\d*"),
requestDurationSeconds: `sum(rate(nginx_ingress_controller_request_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`,
responseDurationSeconds: `sum(rate(nginx_ingress_controller_response_duration_seconds_sum{ingress="${opts.ingress}"}[${this.rateAccuracy}])) by (ingress)`
};

View File

@ -10,7 +10,7 @@ import { workspaceStore } from "../common/workspace-store";
import { preferencesURL } from "../renderer/components/+preferences/preferences.route";
import { clusterViewURL } from "../renderer/components/cluster-manager/cluster-view.route";
import logger from "./logger";
import { isDevelopment } from "../common/vars";
import { isDevelopment, isWindows } from "../common/vars";
import { exitApp } from "./exit-app";
// note: instance of Tray should be saved somewhere, otherwise it disappears
@ -29,7 +29,7 @@ export function initTray(windowManager: WindowManager) {
try {
const menu = createTrayMenu(windowManager);
buildTray(getTrayIcon(), menu);
buildTray(getTrayIcon(), menu, windowManager);
} catch (err) {
logger.error(`[TRAY]: building failed: ${err}`);
}
@ -42,20 +42,25 @@ export function initTray(windowManager: WindowManager) {
};
}
export function buildTray(icon: string | NativeImage, menu: Menu) {
function buildTray(icon: string | NativeImage, menu: Menu, windowManager: WindowManager) {
if (!tray) {
tray = new Tray(icon);
tray.setToolTip(packageInfo.description);
tray.setIgnoreDoubleClickEvents(true);
}
tray.setImage(icon);
tray.setContextMenu(menu);
tray.setImage(icon);
tray.setContextMenu(menu);
if (isWindows) {
tray.on("click", () => {
windowManager.ensureMainWindow();
});
}
}
return tray;
}
export function createTrayMenu(windowManager: WindowManager): Menu {
function createTrayMenu(windowManager: WindowManager): Menu {
return Menu.buildFromTemplate([
{
label: "About Lens",

View File

@ -18,7 +18,7 @@ export const resourceApplierApi = {
.post<KubeJsonApiData[]>("/stack", { data: resource })
.then(data => {
const items = data.map(obj => {
const api = apiManager.getApi(obj.metadata.selfLink);
const api = apiManager.getApiByKind(obj.kind, obj.apiVersion);
if (api) {
return new api.objectConstructor(obj);

View File

@ -22,7 +22,7 @@
height: 18px; // Must be equal to lineHeight variable in pod-log-list.tsx
font-family: $font-monospace;
font-size: smaller;
white-space: pre;
white-space: nowrap;
&:hover {
background: $logRowHoverBackground;

View File

@ -130,10 +130,17 @@ export class Terminal {
fit = () => {
// Since this function is debounced we need to read this value as late as possible
if (!this.isActive) return;
this.fitAddon.fit();
const { cols, rows } = this.xterm;
this.api.sendTerminalSize(cols, rows);
try {
this.fitAddon.fit();
const { cols, rows } = this.xterm;
this.api.sendTerminalSize(cols, rows);
} catch(error) {
console.error(error);
return; // see https://github.com/lensapp/lens/issues/1891
}
};
fitLazy = debounce(this.fit, 250);

View File

@ -2,7 +2,17 @@
Here you can find description of changes we've built into each release. While we try our best to make each upgrade automatic and as smooth as possible, there may be some cases where you might need to do something to ensure the application works smoothly. So please read through the release highlights!
## 4.0.6 (current version)
## 4.0.7 (current version)
- Fix: typo in Prometheus Ingress metrics
- Fix: catch xterm.js fit error
- Fix: Windows tray icon click
- Fix: error on Kubernetes >= 1.20 on object edit
- Fix: multiline log wrapping
- Fix: prevent clusters from initializing multiple times
- Fix: show default workspace on first boot
## 4.0.6
- Don't open Lens at OS login by default
- Disable GPU acceleration by setting an env variable

View File

@ -7756,9 +7756,9 @@ inherits@2.0.3:
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
version "1.3.8"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
init-package-json@^1.10.3:
version "1.10.3"