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:
parent
8cf6d51650
commit
711f98111a
@ -3,7 +3,7 @@
|
||||
"productName": "OpenLens",
|
||||
"description": "OpenLens - Open Source IDE for Kubernetes",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"version": "5.4.1",
|
||||
"version": "5.4.2",
|
||||
"main": "static/build/main.js",
|
||||
"copyright": "© 2021 OpenLens Authors",
|
||||
"license": "MIT",
|
||||
|
||||
@ -36,13 +36,6 @@ describe("HelmChart tests", () => {
|
||||
version: "!",
|
||||
repo: "!",
|
||||
} 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", () => {
|
||||
@ -62,6 +55,14 @@ describe("HelmChart tests", () => {
|
||||
created: "!",
|
||||
digest: "!",
|
||||
} 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({
|
||||
apiVersion: "1",
|
||||
name: "",
|
||||
|
||||
@ -75,7 +75,7 @@ export interface RawHelmChart {
|
||||
version: string;
|
||||
repo: string;
|
||||
created: string;
|
||||
digest: string;
|
||||
digest?: string;
|
||||
kubeVersion?: string;
|
||||
description?: string;
|
||||
home?: string;
|
||||
@ -142,7 +142,7 @@ const helmChartValidator = Joi.object<HelmChart, true, RawHelmChart>({
|
||||
.required(),
|
||||
digest: Joi
|
||||
.string()
|
||||
.required(),
|
||||
.optional(),
|
||||
kubeVersion: Joi
|
||||
.string()
|
||||
.optional(),
|
||||
@ -247,22 +247,22 @@ export interface HelmChart {
|
||||
name: string;
|
||||
version: string;
|
||||
repo: string;
|
||||
kubeVersion?: string;
|
||||
created: string;
|
||||
description: string;
|
||||
digest: string;
|
||||
keywords: string[];
|
||||
home?: string;
|
||||
sources: string[];
|
||||
urls: string[];
|
||||
annotations: Record<string, string>;
|
||||
dependencies: HelmChartDependency[];
|
||||
maintainers: HelmChartMaintainer[];
|
||||
deprecated: boolean;
|
||||
kubeVersion?: string;
|
||||
digest?: string;
|
||||
home?: string;
|
||||
engine?: string;
|
||||
icon?: string;
|
||||
appVersion?: string;
|
||||
type?: string;
|
||||
deprecated: boolean;
|
||||
tillerVersion?: string;
|
||||
}
|
||||
|
||||
@ -324,7 +324,11 @@ export class HelmChart {
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@ -15,7 +15,6 @@ import { Notifications } from "../notifications";
|
||||
import { cssNames } from "../../utils";
|
||||
import { Input } from "../input";
|
||||
import { systemName, maxLength } from "../input/input_validators";
|
||||
import type { KubeObjectMetadata } from "../../../common/k8s-api/kube-object";
|
||||
|
||||
interface Props extends Partial<DialogProps> {
|
||||
}
|
||||
@ -80,6 +79,7 @@ export class CronJobTriggerDialog extends Component<Props> {
|
||||
}, {
|
||||
spec: cronjobDefinition.spec.jobTemplate.spec,
|
||||
metadata: {
|
||||
annotations: { "cronjob.kubernetes.io/instantiate": "manual" },
|
||||
ownerReferences: [{
|
||||
apiVersion: cronjob.apiVersion,
|
||||
blockOwnerDeletion: true,
|
||||
@ -88,7 +88,7 @@ export class CronJobTriggerDialog extends Component<Props> {
|
||||
name: cronjob.metadata.name,
|
||||
uid: cronjob.metadata.uid,
|
||||
}],
|
||||
} as KubeObjectMetadata,
|
||||
},
|
||||
});
|
||||
|
||||
close();
|
||||
|
||||
@ -58,7 +58,7 @@ const NonInjectedLogControls = observer(({ openSaveFileDialog, model }: Dependen
|
||||
{since && (
|
||||
<span>
|
||||
Logs from{" "}
|
||||
<b>{new Date(since[0]).toLocaleString()}</b>
|
||||
<b>{new Date(since).toLocaleString()}</b>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -68,67 +68,76 @@ export class ItemListLayoutContent<I extends ItemObject> extends React.Component
|
||||
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
|
||||
getRow(uid: string) {
|
||||
return (
|
||||
<div key={uid}>
|
||||
<Observer>
|
||||
{() => {
|
||||
const {
|
||||
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);
|
||||
const item = this.props.getItems().find(item => item.getId() === uid);
|
||||
|
||||
if (!item) return null;
|
||||
const itemId = item.getId();
|
||||
|
||||
return (
|
||||
<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>
|
||||
);
|
||||
return this.getTableRow(item);
|
||||
}}
|
||||
</Observer>
|
||||
</div>
|
||||
@ -248,6 +257,7 @@ export class ItemListLayoutContent<I extends ItemObject> extends React.Component
|
||||
selectable={hasDetailsView}
|
||||
sortable={sortingCallbacks}
|
||||
getTableRow={this.getRow}
|
||||
renderRow={virtual ? undefined : this.renderRow}
|
||||
items={items}
|
||||
selectedItemId={selectedItemId}
|
||||
noItems={this.renderNoItems()}
|
||||
|
||||
@ -77,10 +77,6 @@ export const initClusterFrame =
|
||||
});
|
||||
});
|
||||
|
||||
window.addEventListener("online", () => {
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
window.onbeforeunload = () => {
|
||||
logger.info(
|
||||
`${logPrefix} Unload dashboard, clusterId=${(hostedCluster.id)}, frameId=${frameRoutingId}`,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user