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

Release/v5.4.2 (#5005)

* Fix annotation for cronjob when is manually triggered (#4976)

Signed-off-by: Carlos René Mederos Arias <krlosmederos@gmail.com>

* Fix HelmChart validator requiring digest field (#4920)

* Fix HelmChart validator requiring digest field

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fixed non-virtual list row rendering (#4983)

* Remove listener for online event (#4970)

* Fix "logs from" date (#4987)

* release v5.4.2

Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

Co-authored-by: Carlos René Mederos Arias <krlosmederos@gmail.com>
Co-authored-by: Sebastian Malton <sebastian@malton.name>
Co-authored-by: Alex Andreev <alex.andreev.email@gmail.com>
This commit is contained in:
Jim Ehrismann 2022-03-15 09:44:21 -04:00 committed by GitHub
parent 8cf6d51650
commit 711f98111a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 74 deletions

View File

@ -3,7 +3,7 @@
"productName": "OpenLens", "productName": "OpenLens",
"description": "OpenLens - Open Source IDE for Kubernetes", "description": "OpenLens - Open Source IDE for Kubernetes",
"homepage": "https://github.com/lensapp/lens", "homepage": "https://github.com/lensapp/lens",
"version": "5.4.1", "version": "5.4.2",
"main": "static/build/main.js", "main": "static/build/main.js",
"copyright": "© 2021 OpenLens Authors", "copyright": "© 2021 OpenLens Authors",
"license": "MIT", "license": "MIT",

View File

@ -36,13 +36,6 @@ describe("HelmChart tests", () => {
version: "!", version: "!",
repo: "!", repo: "!",
} as any)).toThrowError('"created" is required'); } as any)).toThrowError('"created" is required');
expect(() => HelmChart.create({
apiVersion: "!",
name: "!",
version: "!",
repo: "!",
created: "!",
} as any)).toThrowError('"digest" is required');
}); });
it("should throw on fields being wrong type", () => { it("should throw on fields being wrong type", () => {
@ -62,6 +55,14 @@ describe("HelmChart tests", () => {
created: "!", created: "!",
digest: "!", digest: "!",
} as any)).toThrowError('"name" must be a string'); } as any)).toThrowError('"name" must be a string');
expect(() => HelmChart.create({
apiVersion: "!",
name: "!",
version: "!",
repo: "!",
created: "!",
digest: 1,
} as any)).toThrowError('"digest" must be a string');
expect(() => HelmChart.create({ expect(() => HelmChart.create({
apiVersion: "1", apiVersion: "1",
name: "", name: "",

View File

@ -75,7 +75,7 @@ export interface RawHelmChart {
version: string; version: string;
repo: string; repo: string;
created: string; created: string;
digest: string; digest?: string;
kubeVersion?: string; kubeVersion?: string;
description?: string; description?: string;
home?: string; home?: string;
@ -142,7 +142,7 @@ const helmChartValidator = Joi.object<HelmChart, true, RawHelmChart>({
.required(), .required(),
digest: Joi digest: Joi
.string() .string()
.required(), .optional(),
kubeVersion: Joi kubeVersion: Joi
.string() .string()
.optional(), .optional(),
@ -247,22 +247,22 @@ export interface HelmChart {
name: string; name: string;
version: string; version: string;
repo: string; repo: string;
kubeVersion?: string;
created: string; created: string;
description: string; description: string;
digest: string;
keywords: string[]; keywords: string[];
home?: string;
sources: string[]; sources: string[];
urls: string[]; urls: string[];
annotations: Record<string, string>; annotations: Record<string, string>;
dependencies: HelmChartDependency[]; dependencies: HelmChartDependency[];
maintainers: HelmChartMaintainer[]; maintainers: HelmChartMaintainer[];
deprecated: boolean;
kubeVersion?: string;
digest?: string;
home?: string;
engine?: string; engine?: string;
icon?: string; icon?: string;
appVersion?: string; appVersion?: string;
type?: string; type?: string;
deprecated: boolean;
tillerVersion?: string; tillerVersion?: string;
} }
@ -324,7 +324,11 @@ export class HelmChart {
} }
getId(): string { getId(): string {
return `${this.repo}:${this.apiVersion}/${this.name}@${this.getAppVersion()}+${this.digest}`; const digestPart = this.digest
? `+${this.digest}`
: "";
return `${this.repo}:${this.apiVersion}/${this.name}@${this.getAppVersion()}${digestPart}`;
} }
getName(): string { getName(): string {

View File

@ -15,7 +15,6 @@ import { Notifications } from "../notifications";
import { cssNames } from "../../utils"; import { cssNames } from "../../utils";
import { Input } from "../input"; import { Input } from "../input";
import { systemName, maxLength } from "../input/input_validators"; import { systemName, maxLength } from "../input/input_validators";
import type { KubeObjectMetadata } from "../../../common/k8s-api/kube-object";
interface Props extends Partial<DialogProps> { interface Props extends Partial<DialogProps> {
} }
@ -80,6 +79,7 @@ export class CronJobTriggerDialog extends Component<Props> {
}, { }, {
spec: cronjobDefinition.spec.jobTemplate.spec, spec: cronjobDefinition.spec.jobTemplate.spec,
metadata: { metadata: {
annotations: { "cronjob.kubernetes.io/instantiate": "manual" },
ownerReferences: [{ ownerReferences: [{
apiVersion: cronjob.apiVersion, apiVersion: cronjob.apiVersion,
blockOwnerDeletion: true, blockOwnerDeletion: true,
@ -88,7 +88,7 @@ export class CronJobTriggerDialog extends Component<Props> {
name: cronjob.metadata.name, name: cronjob.metadata.name,
uid: cronjob.metadata.uid, uid: cronjob.metadata.uid,
}], }],
} as KubeObjectMetadata, },
}); });
close(); close();

View File

@ -58,7 +58,7 @@ const NonInjectedLogControls = observer(({ openSaveFileDialog, model }: Dependen
{since && ( {since && (
<span> <span>
Logs from{" "} Logs from{" "}
<b>{new Date(since[0]).toLocaleString()}</b> <b>{new Date(since).toLocaleString()}</b>
</span> </span>
)} )}
</div> </div>

View File

@ -68,67 +68,76 @@ export class ItemListLayoutContent<I extends ItemObject> extends React.Component
return this.props.store.failedLoading; return this.props.store.failedLoading;
} }
@boundMethod
renderRow(item: I) {
return this.getTableRow(item);
}
getTableRow(item: I) {
const {
isSelectable, renderTableHeader, renderTableContents, renderItemMenu,
store, hasDetailsView, onDetails,
copyClassNameFromHeadCells, customizeTableRowProps, detailsItem,
} = this.props;
const { isSelected } = store;
return (
<TableRow
nowrap
searchItem={item}
sortItem={item}
selected={detailsItem && detailsItem.getId() === item.getId()}
onClick={hasDetailsView ? prevDefault(() => onDetails(item)) : undefined}
{...customizeTableRowProps(item)}
>
{isSelectable && (
<TableCell
checkbox
isChecked={isSelected(item)}
onClick={prevDefault(() => store.toggleSelection(item))}
/>
)}
{renderTableContents(item).map((content, index) => {
const cellProps: TableCellProps = isReactNode(content)
? { children: content }
: content;
const headCell = renderTableHeader?.[index];
if (copyClassNameFromHeadCells && headCell) {
cellProps.className = cssNames(
cellProps.className,
headCell.className,
);
}
if (!headCell || this.showColumn(headCell)) {
return <TableCell key={index} {...cellProps} />;
}
return null;
})}
{renderItemMenu && (
<TableCell className="menu">
<div onClick={stopPropagation}>
{renderItemMenu(item, store)}
</div>
</TableCell>
)}
</TableRow>
);
}
@boundMethod @boundMethod
getRow(uid: string) { getRow(uid: string) {
return ( return (
<div key={uid}> <div key={uid}>
<Observer> <Observer>
{() => { {() => {
const { const item = this.props.getItems().find(item => item.getId() === uid);
isSelectable, renderTableHeader, renderTableContents, renderItemMenu,
store, hasDetailsView, onDetails,
copyClassNameFromHeadCells, customizeTableRowProps, detailsItem,
} = this.props;
const { isSelected } = store;
const item = this.props.getItems().find(item => item.getId() == uid);
if (!item) return null; if (!item) return null;
const itemId = item.getId();
return ( return this.getTableRow(item);
<TableRow
nowrap
searchItem={item}
sortItem={item}
selected={detailsItem && detailsItem.getId() === itemId}
onClick={hasDetailsView ? prevDefault(() => onDetails(item)) : undefined}
{...customizeTableRowProps(item)}
>
{isSelectable && (
<TableCell
checkbox
isChecked={isSelected(item)}
onClick={prevDefault(() => store.toggleSelection(item))}
/>
)}
{renderTableContents(item).map((content, index) => {
const cellProps: TableCellProps = isReactNode(content)
? { children: content }
: content;
const headCell = renderTableHeader?.[index];
if (copyClassNameFromHeadCells && headCell) {
cellProps.className = cssNames(
cellProps.className,
headCell.className,
);
}
if (!headCell || this.showColumn(headCell)) {
return <TableCell key={index} {...cellProps} />;
}
return null;
})}
{renderItemMenu && (
<TableCell className="menu">
<div onClick={stopPropagation}>
{renderItemMenu(item, store)}
</div>
</TableCell>
)}
</TableRow>
);
}} }}
</Observer> </Observer>
</div> </div>
@ -248,6 +257,7 @@ export class ItemListLayoutContent<I extends ItemObject> extends React.Component
selectable={hasDetailsView} selectable={hasDetailsView}
sortable={sortingCallbacks} sortable={sortingCallbacks}
getTableRow={this.getRow} getTableRow={this.getRow}
renderRow={virtual ? undefined : this.renderRow}
items={items} items={items}
selectedItemId={selectedItemId} selectedItemId={selectedItemId}
noItems={this.renderNoItems()} noItems={this.renderNoItems()}

View File

@ -77,10 +77,6 @@ export const initClusterFrame =
}); });
}); });
window.addEventListener("online", () => {
window.location.reload();
});
window.onbeforeunload = () => { window.onbeforeunload = () => {
logger.info( logger.info(
`${logPrefix} Unload dashboard, clusterId=${(hostedCluster.id)}, frameId=${frameRoutingId}`, `${logPrefix} Unload dashboard, clusterId=${(hostedCluster.id)}, frameId=${frameRoutingId}`,