mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into fix-1898/watch-api-streaming
# Conflicts: # src/renderer/api/kube-watch-api.ts # src/renderer/components/+namespaces/namespace.store.ts # src/renderer/components/+workloads-overview/overview.tsx # src/renderer/components/item-object-list/item-list-layout.tsx
This commit is contained in:
commit
7b4e060067
@ -46,6 +46,8 @@ module.exports = {
|
|||||||
"avoidEscape": true,
|
"avoidEscape": true,
|
||||||
"allowTemplateLiterals": true,
|
"allowTemplateLiterals": true,
|
||||||
}],
|
}],
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"eol-last": ["error", "always"],
|
||||||
"semi": ["error", "always"],
|
"semi": ["error", "always"],
|
||||||
"object-shorthand": "error",
|
"object-shorthand": "error",
|
||||||
"prefer-template": "error",
|
"prefer-template": "error",
|
||||||
@ -101,6 +103,8 @@ module.exports = {
|
|||||||
}],
|
}],
|
||||||
"semi": "off",
|
"semi": "off",
|
||||||
"@typescript-eslint/semi": ["error"],
|
"@typescript-eslint/semi": ["error"],
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"eol-last": ["error", "always"],
|
||||||
"object-shorthand": "error",
|
"object-shorthand": "error",
|
||||||
"prefer-template": "error",
|
"prefer-template": "error",
|
||||||
"template-curly-spacing": "error",
|
"template-curly-spacing": "error",
|
||||||
@ -162,6 +166,8 @@ module.exports = {
|
|||||||
}],
|
}],
|
||||||
"semi": "off",
|
"semi": "off",
|
||||||
"@typescript-eslint/semi": ["error"],
|
"@typescript-eslint/semi": ["error"],
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"eol-last": ["error", "always"],
|
||||||
"object-shorthand": "error",
|
"object-shorthand": "error",
|
||||||
"prefer-template": "error",
|
"prefer-template": "error",
|
||||||
"template-curly-spacing": "error",
|
"template-curly-spacing": "error",
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
module.exports = {};
|
module.exports = {};
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
module.exports = {};
|
module.exports = {};
|
||||||
|
|||||||
@ -56,4 +56,4 @@ export function resolveStatusForCronJobs(cronJob: K8sApi.CronJob): K8sApi.KubeOb
|
|||||||
text: `${event.message}`,
|
text: `${event.message}`,
|
||||||
timestamp: event.metadata.creationTimestamp
|
timestamp: event.metadata.creationTimestamp
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -219,7 +219,7 @@
|
|||||||
"request-promise-native": "^1.0.8",
|
"request-promise-native": "^1.0.8",
|
||||||
"semver": "^7.3.2",
|
"semver": "^7.3.2",
|
||||||
"serializr": "^2.0.3",
|
"serializr": "^2.0.3",
|
||||||
"shell-env": "^3.0.0",
|
"shell-env": "^3.0.1",
|
||||||
"spdy": "^4.0.2",
|
"spdy": "^4.0.2",
|
||||||
"tar": "^6.0.5",
|
"tar": "^6.0.5",
|
||||||
"tcp-port-used": "^1.0.1",
|
"tcp-port-used": "^1.0.1",
|
||||||
|
|||||||
@ -77,4 +77,4 @@ describe("search store tests", () => {
|
|||||||
searchStore.onSearch(logs, "Starting");
|
searchStore.onSearch(logs, "Starting");
|
||||||
expect(searchStore.totalFinds).toBe(2);
|
expect(searchStore.totalFinds).toBe(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -101,4 +101,4 @@ describe("user store tests", () => {
|
|||||||
expect(us.lastSeenAppVersion).toBe("0.0.0");
|
expect(us.lastSeenAppVersion).toBe("0.0.0");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,4 +10,4 @@ export class ExecValidationNotFoundError extends Error {
|
|||||||
this.name = this.constructor.name;
|
this.name = this.constructor.name;
|
||||||
Error.captureStackTrace(this, this.constructor);
|
Error.captureStackTrace(this, this.constructor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -175,4 +175,4 @@ export function validateKubeConfig (config: KubeConfig) {
|
|||||||
throw new ExecValidationNotFoundError(execCommand, isAbsolute);
|
throw new ExecValidationNotFoundError(execCommand, isAbsolute);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,4 +10,4 @@ import { PrometheusProviderRegistry } from "../main/prometheus/provider-registry
|
|||||||
PrometheusProviderRegistry.registerProvider(provider.id, provider);
|
PrometheusProviderRegistry.registerProvider(provider.id, provider);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const prometheusProviders = PrometheusProviderRegistry.getProviders();
|
export const prometheusProviders = PrometheusProviderRegistry.getProviders();
|
||||||
|
|||||||
@ -133,4 +133,4 @@ export class SearchStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const searchStore = new SearchStore;
|
export const searchStore = new SearchStore;
|
||||||
|
|||||||
@ -28,4 +28,4 @@ describe("split array on element tests", () => {
|
|||||||
test("ten elements, in end array", () => {
|
test("ten elements, in end array", () => {
|
||||||
expect(splitArray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9)).toStrictEqual([[0, 1, 2, 3, 4, 5, 6, 7, 8], [], true]);
|
expect(splitArray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 9)).toStrictEqual([[0, 1, 2, 3, 4, 5, 6, 7, 8], [], true]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -26,4 +26,4 @@ class Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export { Singleton };
|
export { Singleton };
|
||||||
export default Singleton;
|
export default Singleton;
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./registrations";
|
export * from "./registrations";
|
||||||
|
|||||||
@ -5,4 +5,4 @@ export type { KubeObjectMenuRegistration, KubeObjectMenuComponents } from "../re
|
|||||||
export type { KubeObjectStatusRegistration } from "../registries/kube-object-status-registry";
|
export type { KubeObjectStatusRegistration } from "../registries/kube-object-status-registry";
|
||||||
export type { PageRegistration, RegisteredPage, PageParams, PageComponentProps, PageComponents, PageTarget } from "../registries/page-registry";
|
export type { PageRegistration, RegisteredPage, PageParams, PageComponentProps, PageComponents, PageTarget } from "../registries/page-registry";
|
||||||
export type { PageMenuRegistration, ClusterPageMenuRegistration, PageMenuComponents } from "../registries/page-menu-registry";
|
export type { PageMenuRegistration, ClusterPageMenuRegistration, PageMenuComponents } from "../registries/page-menu-registry";
|
||||||
export type { StatusBarRegistration } from "../registries/status-bar-registry";
|
export type { StatusBarRegistration } from "../registries/status-bar-registry";
|
||||||
|
|||||||
@ -8,4 +8,4 @@ export enum KubeObjectStatusLevel {
|
|||||||
INFO = 1,
|
INFO = 1,
|
||||||
WARNING = 2,
|
WARNING = 2,
|
||||||
CRITICAL = 3
|
CRITICAL = 3
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,4 +2,4 @@ import { themeStore } from "../../renderer/theme.store";
|
|||||||
|
|
||||||
export function getActiveTheme() {
|
export function getActiveTheme() {
|
||||||
return themeStore.activeTheme;
|
return themeStore.activeTheme;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,4 +31,4 @@ export class BaseClusterDetector {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,4 +23,4 @@ export class ClusterIdDetector extends BaseClusterDetector {
|
|||||||
|
|
||||||
return response.metadata.uid;
|
return response.metadata.uid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,4 +48,4 @@ detectorRegistry.add(ClusterIdDetector);
|
|||||||
detectorRegistry.add(LastSeenDetector);
|
detectorRegistry.add(LastSeenDetector);
|
||||||
detectorRegistry.add(VersionDetector);
|
detectorRegistry.add(VersionDetector);
|
||||||
detectorRegistry.add(DistributionDetector);
|
detectorRegistry.add(DistributionDetector);
|
||||||
detectorRegistry.add(NodesCountDetector);
|
detectorRegistry.add(NodesCountDetector);
|
||||||
|
|||||||
@ -11,4 +11,4 @@ export class LastSeenDetector extends BaseClusterDetector {
|
|||||||
|
|
||||||
return { value: new Date().toJSON(), accuracy: 100 };
|
return { value: new Date().toJSON(), accuracy: 100 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,4 +16,4 @@ export class NodesCountDetector extends BaseClusterDetector {
|
|||||||
|
|
||||||
return response.items.length;
|
return response.items.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,4 +16,4 @@ export class VersionDetector extends BaseClusterDetector {
|
|||||||
|
|
||||||
return response.gitVersion;
|
return response.gitVersion;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,4 +18,4 @@ export default {
|
|||||||
...version270Beta1,
|
...version270Beta1,
|
||||||
...version360Beta1,
|
...version360Beta1,
|
||||||
...snap
|
...snap
|
||||||
};
|
};
|
||||||
|
|||||||
@ -79,4 +79,4 @@ describe("KubeApi", () => {
|
|||||||
expect(kubeApi.apiPrefix).toEqual("/apis");
|
expect(kubeApi.apiPrefix).toEqual("/apis");
|
||||||
expect(kubeApi.apiGroup).toEqual("extensions");
|
expect(kubeApi.apiGroup).toEqual("extensions");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import get from "lodash/get";
|
import get from "lodash/get";
|
||||||
import { KubeObject } from "./kube-object";
|
import { KubeObject } from "./kube-object";
|
||||||
|
|
||||||
interface IToleration {
|
export interface IToleration {
|
||||||
key?: string;
|
key?: string;
|
||||||
operator?: string;
|
operator?: string;
|
||||||
effect?: string;
|
effect?: string;
|
||||||
@ -82,4 +82,4 @@ export class WorkloadKubeObject extends KubeObject {
|
|||||||
|
|
||||||
return Object.keys(affinity).length;
|
return Object.keys(affinity).length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,4 +11,4 @@ export interface IHelmChartsRouteParams {
|
|||||||
repo?: string;
|
repo?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const helmChartsURL = buildURL<IHelmChartsRouteParams>(helmChartsRoute.path);
|
export const helmChartsURL = buildURL<IHelmChartsRouteParams>(helmChartsRoute.path);
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export * from "./helm-charts";
|
export * from "./helm-charts";
|
||||||
export * from "./helm-charts.route";
|
export * from "./helm-charts.route";
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export * from "./releases";
|
export * from "./releases";
|
||||||
export * from "./release.route";
|
export * from "./release.route";
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export * from "./apps";
|
export * from "./apps";
|
||||||
export * from "./apps.route";
|
export * from "./apps.route";
|
||||||
|
|||||||
@ -48,4 +48,4 @@ export class ClusterHomeDirSetting extends React.Component<Props> {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,4 +45,4 @@ export class ClusterNameSetting extends React.Component<Props> {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,4 +45,4 @@ export class ClusterProxySetting extends React.Component<Props> {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,4 +25,4 @@ export class General extends React.Component<Props> {
|
|||||||
<ClusterAccessibleNamespaces cluster={this.props.cluster} />
|
<ClusterAccessibleNamespaces cluster={this.props.cluster} />
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,4 +17,4 @@ export class Removal extends React.Component<Props> {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,4 +58,4 @@ export class Status extends React.Component<Props> {
|
|||||||
</div>
|
</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,11 +23,13 @@ interface IWarning extends ItemObject {
|
|||||||
kind: string;
|
kind: string;
|
||||||
message: string;
|
message: string;
|
||||||
selfLink: string;
|
selfLink: string;
|
||||||
|
age: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum sortBy {
|
enum sortBy {
|
||||||
type = "type",
|
type = "type",
|
||||||
object = "object"
|
object = "object",
|
||||||
|
age = "age",
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -35,6 +37,7 @@ export class ClusterIssues extends React.Component<Props> {
|
|||||||
private sortCallbacks = {
|
private sortCallbacks = {
|
||||||
[sortBy.type]: (warning: IWarning) => warning.kind,
|
[sortBy.type]: (warning: IWarning) => warning.kind,
|
||||||
[sortBy.object]: (warning: IWarning) => warning.getName(),
|
[sortBy.object]: (warning: IWarning) => warning.getName(),
|
||||||
|
[sortBy.age]: (warning: IWarning) => warning.age || "",
|
||||||
};
|
};
|
||||||
|
|
||||||
@computed get warnings() {
|
@computed get warnings() {
|
||||||
@ -42,15 +45,16 @@ export class ClusterIssues extends React.Component<Props> {
|
|||||||
|
|
||||||
// Node bad conditions
|
// Node bad conditions
|
||||||
nodesStore.items.forEach(node => {
|
nodesStore.items.forEach(node => {
|
||||||
const { kind, selfLink, getId, getName } = node;
|
const { kind, selfLink, getId, getName, getAge } = node;
|
||||||
|
|
||||||
node.getWarningConditions().forEach(({ message }) => {
|
node.getWarningConditions().forEach(({ message }) => {
|
||||||
warnings.push({
|
warnings.push({
|
||||||
kind,
|
age: getAge(),
|
||||||
getId,
|
getId,
|
||||||
getName,
|
getName,
|
||||||
selfLink,
|
kind,
|
||||||
message,
|
message,
|
||||||
|
selfLink,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -59,12 +63,13 @@ export class ClusterIssues extends React.Component<Props> {
|
|||||||
const events = eventStore.getWarnings();
|
const events = eventStore.getWarnings();
|
||||||
|
|
||||||
events.forEach(error => {
|
events.forEach(error => {
|
||||||
const { message, involvedObject } = error;
|
const { message, involvedObject, getAge } = error;
|
||||||
const { uid, name, kind } = involvedObject;
|
const { uid, name, kind } = involvedObject;
|
||||||
|
|
||||||
warnings.push({
|
warnings.push({
|
||||||
getId: () => uid,
|
getId: () => uid,
|
||||||
getName: () => name,
|
getName: () => name,
|
||||||
|
age: getAge(),
|
||||||
message,
|
message,
|
||||||
kind,
|
kind,
|
||||||
selfLink: lookupApiLink(involvedObject, error),
|
selfLink: lookupApiLink(involvedObject, error),
|
||||||
@ -78,7 +83,7 @@ export class ClusterIssues extends React.Component<Props> {
|
|||||||
getTableRow(uid: string) {
|
getTableRow(uid: string) {
|
||||||
const { warnings } = this;
|
const { warnings } = this;
|
||||||
const warning = warnings.find(warn => warn.getId() == uid);
|
const warning = warnings.find(warn => warn.getId() == uid);
|
||||||
const { getId, getName, message, kind, selfLink } = warning;
|
const { getId, getName, message, kind, selfLink, age } = warning;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TableRow
|
<TableRow
|
||||||
@ -96,6 +101,9 @@ export class ClusterIssues extends React.Component<Props> {
|
|||||||
<TableCell className="kind">
|
<TableCell className="kind">
|
||||||
{kind}
|
{kind}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
<TableCell className="age">
|
||||||
|
{age}
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -139,6 +147,7 @@ export class ClusterIssues extends React.Component<Props> {
|
|||||||
<TableCell className="message">Message</TableCell>
|
<TableCell className="message">Message</TableCell>
|
||||||
<TableCell className="object" sortBy={sortBy.object}>Object</TableCell>
|
<TableCell className="object" sortBy={sortBy.object}>Object</TableCell>
|
||||||
<TableCell className="kind" sortBy={sortBy.type}>Type</TableCell>
|
<TableCell className="kind" sortBy={sortBy.type}>Type</TableCell>
|
||||||
|
<TableCell className="timestamp" sortBy={sortBy.age}>Age</TableCell>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
</Table>
|
</Table>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -95,4 +95,4 @@ export const ClusterMetrics = observer(() => {
|
|||||||
{renderMetrics()}
|
{renderMetrics()}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export * from "./landing-page.route";
|
export * from "./landing-page.route";
|
||||||
export * from "./landing-page";
|
export * from "./landing-page";
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
export * from "./pod-security-policies.route";
|
export * from "./pod-security-policies.route";
|
||||||
export * from "./pod-security-policies";
|
export * from "./pod-security-policies";
|
||||||
export * from "./pod-security-policy-details";
|
export * from "./pod-security-policy-details";
|
||||||
|
|||||||
@ -47,4 +47,4 @@ export const rolesStore = new RolesStore();
|
|||||||
apiManager.registerStore(rolesStore, [
|
apiManager.registerStore(rolesStore, [
|
||||||
roleApi,
|
roleApi,
|
||||||
clusterRoleApi,
|
clusterRoleApi,
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
export * from "./service-accounts";
|
export * from "./service-accounts";
|
||||||
export * from "./service-accounts-details";
|
export * from "./service-accounts-details";
|
||||||
export * from "./create-service-account-dialog";
|
export * from "./create-service-account-dialog";
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export * from "./user-management";
|
export * from "./user-management";
|
||||||
export * from "./user-management.route";
|
export * from "./user-management.route";
|
||||||
|
|||||||
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* @jest-environment jsdom
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import "@testing-library/jest-dom/extend-expect";
|
||||||
|
import { fireEvent, render } from "@testing-library/react";
|
||||||
|
import { IToleration } from "../../../api/workload-kube-object";
|
||||||
|
import { PodTolerations } from "../pod-tolerations";
|
||||||
|
|
||||||
|
const tolerations: IToleration[] =[
|
||||||
|
{
|
||||||
|
key: "CriticalAddonsOnly",
|
||||||
|
operator: "Exist",
|
||||||
|
effect: "NoExecute",
|
||||||
|
tolerationSeconds: 3600
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "node.kubernetes.io/not-ready",
|
||||||
|
operator: "NoExist",
|
||||||
|
effect: "NoSchedule",
|
||||||
|
tolerationSeconds: 7200
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
describe("<PodTolerations />", () => {
|
||||||
|
it("renders w/o errors", () => {
|
||||||
|
const { container } = render(<PodTolerations tolerations={tolerations} />);
|
||||||
|
|
||||||
|
expect(container).toBeInstanceOf(HTMLElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows all tolerations", () => {
|
||||||
|
const { container } = render(<PodTolerations tolerations={tolerations} />);
|
||||||
|
const rows = container.querySelectorAll(".TableRow");
|
||||||
|
|
||||||
|
expect(rows[0].querySelector(".key").textContent).toBe("CriticalAddonsOnly");
|
||||||
|
expect(rows[0].querySelector(".operator").textContent).toBe("Exist");
|
||||||
|
expect(rows[0].querySelector(".effect").textContent).toBe("NoExecute");
|
||||||
|
expect(rows[0].querySelector(".seconds").textContent).toBe("3600");
|
||||||
|
|
||||||
|
expect(rows[1].querySelector(".key").textContent).toBe("node.kubernetes.io/not-ready");
|
||||||
|
expect(rows[1].querySelector(".operator").textContent).toBe("NoExist");
|
||||||
|
expect(rows[1].querySelector(".effect").textContent).toBe("NoSchedule");
|
||||||
|
expect(rows[1].querySelector(".seconds").textContent).toBe("7200");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sorts table properly", () => {
|
||||||
|
const { container, getByText } = render(<PodTolerations tolerations={tolerations} />);
|
||||||
|
const headCell = getByText("Key");
|
||||||
|
|
||||||
|
fireEvent.click(headCell);
|
||||||
|
fireEvent.click(headCell);
|
||||||
|
|
||||||
|
const rows = container.querySelectorAll(".TableRow");
|
||||||
|
|
||||||
|
expect(rows[0].querySelector(".key").textContent).toBe("node.kubernetes.io/not-ready");
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -1,2 +1,2 @@
|
|||||||
export * from "./pods";
|
export * from "./pods";
|
||||||
export * from "./pod-details";
|
export * from "./pod-details";
|
||||||
|
|||||||
@ -27,4 +27,4 @@ export class PodDetailsStatuses extends React.Component<Props> {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,23 @@
|
|||||||
.PodDetailsTolerations {
|
.PodDetailsTolerations {
|
||||||
.toleration {
|
grid-template-columns: auto;
|
||||||
margin-bottom: $margin;
|
|
||||||
|
.PodTolerations {
|
||||||
|
margin-top: var(--margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expanding value cell to cover 2 columns (whole Drawer width)
|
||||||
|
|
||||||
|
> .name {
|
||||||
|
grid-row-start: 1;
|
||||||
|
grid-column-start: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .value {
|
||||||
|
grid-row-start: 1;
|
||||||
|
grid-column-start: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.DrawerParamToggler > .params {
|
||||||
|
margin-left: var(--drawer-item-title-width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,10 +1,11 @@
|
|||||||
import "./pod-details-tolerations.scss";
|
import "./pod-details-tolerations.scss";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Pod, Deployment, DaemonSet, StatefulSet, ReplicaSet, Job } from "../../api/endpoints";
|
|
||||||
import { DrawerParamToggler, DrawerItem } from "../drawer";
|
import { DrawerParamToggler, DrawerItem } from "../drawer";
|
||||||
|
import { WorkloadKubeObject } from "../../api/workload-kube-object";
|
||||||
|
import { PodTolerations } from "./pod-tolerations";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
workload: Pod | Deployment | DaemonSet | StatefulSet | ReplicaSet | Job;
|
workload: WorkloadKubeObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PodDetailsTolerations extends React.Component<Props> {
|
export class PodDetailsTolerations extends React.Component<Props> {
|
||||||
@ -17,20 +18,7 @@ export class PodDetailsTolerations extends React.Component<Props> {
|
|||||||
return (
|
return (
|
||||||
<DrawerItem name="Tolerations" className="PodDetailsTolerations">
|
<DrawerItem name="Tolerations" className="PodDetailsTolerations">
|
||||||
<DrawerParamToggler label={tolerations.length}>
|
<DrawerParamToggler label={tolerations.length}>
|
||||||
{
|
<PodTolerations tolerations={tolerations} />
|
||||||
tolerations.map((toleration, index) => {
|
|
||||||
const { key, operator, effect, tolerationSeconds } = toleration;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="toleration" key={index}>
|
|
||||||
<DrawerItem name="Key">{key}</DrawerItem>
|
|
||||||
{operator && <DrawerItem name="Operator">{operator}</DrawerItem>}
|
|
||||||
{effect && <DrawerItem name="Effect">{effect}</DrawerItem>}
|
|
||||||
{!!tolerationSeconds && <DrawerItem name="Effect">{tolerationSeconds}</DrawerItem>}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</DrawerParamToggler>
|
</DrawerParamToggler>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
);
|
);
|
||||||
|
|||||||
14
src/renderer/components/+workloads-pods/pod-tolerations.scss
Normal file
14
src/renderer/components/+workloads-pods/pod-tolerations.scss
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
.PodTolerations {
|
||||||
|
.TableHead {
|
||||||
|
background-color: var(--drawerSubtitleBackground);
|
||||||
|
}
|
||||||
|
|
||||||
|
.TableCell {
|
||||||
|
white-space: normal;
|
||||||
|
word-break: normal;
|
||||||
|
|
||||||
|
&.key {
|
||||||
|
flex-grow: 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/renderer/components/+workloads-pods/pod-tolerations.tsx
Normal file
63
src/renderer/components/+workloads-pods/pod-tolerations.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import "./pod-tolerations.scss";
|
||||||
|
import React from "react";
|
||||||
|
import uniqueId from "lodash/uniqueId";
|
||||||
|
|
||||||
|
import { IToleration } from "../../api/workload-kube-object";
|
||||||
|
import { Table, TableCell, TableHead, TableRow } from "../table";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
tolerations: IToleration[];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum sortBy {
|
||||||
|
Key = "key",
|
||||||
|
Operator = "operator",
|
||||||
|
Effect = "effect",
|
||||||
|
Seconds = "seconds",
|
||||||
|
}
|
||||||
|
|
||||||
|
const sortingCallbacks = {
|
||||||
|
[sortBy.Key]: (toleration: IToleration) => toleration.key,
|
||||||
|
[sortBy.Operator]: (toleration: IToleration) => toleration.operator,
|
||||||
|
[sortBy.Effect]: (toleration: IToleration) => toleration.effect,
|
||||||
|
[sortBy.Seconds]: (toleration: IToleration) => toleration.tolerationSeconds,
|
||||||
|
};
|
||||||
|
|
||||||
|
const getTableRow = (toleration: IToleration) => {
|
||||||
|
const { key, operator, effect, tolerationSeconds } = toleration;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TableRow
|
||||||
|
key={uniqueId("toleration-")}
|
||||||
|
sortItem={toleration}
|
||||||
|
nowrap
|
||||||
|
>
|
||||||
|
<TableCell className="key">{key}</TableCell>
|
||||||
|
<TableCell className="operator">{operator}</TableCell>
|
||||||
|
<TableCell className="effect">{effect}</TableCell>
|
||||||
|
<TableCell className="seconds">{tolerationSeconds}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export function PodTolerations({ tolerations }: Props) {
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
selectable
|
||||||
|
scrollable={false}
|
||||||
|
sortable={sortingCallbacks}
|
||||||
|
sortSyncWithUrl={false}
|
||||||
|
className="PodTolerations"
|
||||||
|
>
|
||||||
|
<TableHead sticky={false}>
|
||||||
|
<TableCell className="key" sortBy={sortBy.Key}>Key</TableCell>
|
||||||
|
<TableCell className="operator" sortBy={sortBy.Operator}>Operator</TableCell>
|
||||||
|
<TableCell className="effect" sortBy={sortBy.Effect}>Effect</TableCell>
|
||||||
|
<TableCell className="seconds" sortBy={sortBy.Seconds}>Seconds</TableCell>
|
||||||
|
</TableHead>
|
||||||
|
{
|
||||||
|
tolerations.map(getTableRow)
|
||||||
|
}
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,2 +1,2 @@
|
|||||||
export * from "./statefulsets";
|
export * from "./statefulsets";
|
||||||
export * from "./statefulset-details";
|
export * from "./statefulset-details";
|
||||||
|
|||||||
@ -154,4 +154,4 @@ export class AceEditor extends React.Component<Props, State> {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./ace-editor";
|
export * from "./ace-editor";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./add-remove-buttons";
|
export * from "./add-remove-buttons";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./animate";
|
export * from "./animate";
|
||||||
|
|||||||
@ -39,4 +39,4 @@ export const BackgroundBlock = {
|
|||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -220,4 +220,4 @@ export const cpuOptions: ChartOptions = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -213,4 +213,4 @@ export class Chart extends React.Component<ChartProps> {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
export * from "./chart";
|
export * from "./chart";
|
||||||
export * from "./pie-chart";
|
export * from "./pie-chart";
|
||||||
export * from "./bar-chart";
|
export * from "./bar-chart";
|
||||||
|
|||||||
@ -64,4 +64,4 @@ export class PieChart extends React.Component<Props> {
|
|||||||
|
|
||||||
ChartJS.Tooltip.positioners.cursor = function (elements: any, position: { x: number; y: number }) {
|
ChartJS.Tooltip.positioners.cursor = function (elements: any, position: { x: number; y: number }) {
|
||||||
return position;
|
return position;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -42,4 +42,4 @@ export function useRealTimeMetrics(metrics: IMetricValues, chartData: IChartData
|
|||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,4 +95,4 @@ export const ZebraStripes = {
|
|||||||
cover.style.backgroundPositionX = `${-step * minutes}px`;
|
cover.style.backgroundPositionX = `${-step * minutes}px`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -50,4 +50,4 @@ export class Checkbox extends React.PureComponent<CheckboxProps> {
|
|||||||
</label>
|
</label>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./checkbox";
|
export * from "./checkbox";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./cluster-icon";
|
export * from "./cluster-icon";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./confirm-dialog";
|
export * from "./confirm-dialog";
|
||||||
|
|||||||
@ -48,4 +48,4 @@ export const DockTabs = ({ tabs, autoFocus, selectedTab, onChangeTab }: Props) =
|
|||||||
{tabs.map(tab => <Fragment key={tab.id}>{renderTab(tab)}</Fragment>)}
|
{tabs.map(tab => <Fragment key={tab.id}>{renderTab(tab)}</Fragment>)}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,12 +1,16 @@
|
|||||||
.InfoPanel {
|
.InfoPanel {
|
||||||
@include hidden-scrollbar;
|
@include hidden-scrollbar;
|
||||||
|
|
||||||
background: $dockInfoBackground;
|
background: var(--dockInfoBackground);
|
||||||
padding: $padding $padding * 2;
|
padding: var(--padding) calc(var(--padding) * 2);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
|
||||||
.Spinner {
|
.Spinner {
|
||||||
margin-right: $padding;
|
margin-right: var(--padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
.Badge {
|
||||||
|
background-color: var(--dockBadgeBackground);
|
||||||
}
|
}
|
||||||
|
|
||||||
> .controls {
|
> .controls {
|
||||||
@ -15,8 +19,8 @@
|
|||||||
|
|
||||||
&:not(:empty) + .info {
|
&:not(:empty) + .info {
|
||||||
min-height: 25px;
|
min-height: 25px;
|
||||||
padding-left: $padding;
|
padding-left: var(--padding);
|
||||||
padding-right: $padding;
|
padding-right: var(--padding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,7 +41,12 @@ export const LogControls = observer((props: Props) => {
|
|||||||
return (
|
return (
|
||||||
<div className={cssNames("LogControls flex gaps align-center justify-space-between wrap")}>
|
<div className={cssNames("LogControls flex gaps align-center justify-space-between wrap")}>
|
||||||
<div className="time-range">
|
<div className="time-range">
|
||||||
{since && `Logs from ${new Date(since[0]).toLocaleString()}`}
|
{since && (
|
||||||
|
<span>
|
||||||
|
Logs from{" "}
|
||||||
|
<b>{new Date(since[0]).toLocaleString()}</b>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gaps align-center">
|
<div className="flex gaps align-center">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
.DrawerItem {
|
.DrawerItem {
|
||||||
|
--drawer-item-title-width: 30%;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(30%, min-content) auto;
|
grid-template-columns: minmax(var(--drawer-item-title-width), min-content) auto;
|
||||||
border-bottom: 1px solid $borderFaintColor;
|
border-bottom: 1px solid $borderFaintColor;
|
||||||
padding: $padding 0;
|
padding: $padding 0;
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export class DrawerParamToggler extends React.Component<DrawerParamTogglerProps,
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="DrawerParamToggler">
|
<div className="DrawerParamToggler">
|
||||||
<div className="flex gaps align-center">
|
<div className="flex gaps align-center params">
|
||||||
<div className="param-label">{label}</div>
|
<div className="param-label">{label}</div>
|
||||||
<div className="param-link" onClick={this.toggle}>
|
<div className="param-link" onClick={this.toggle}>
|
||||||
<span className="param-link-text">{link}</span>
|
<span className="param-link-text">{link}</span>
|
||||||
|
|||||||
@ -69,7 +69,6 @@
|
|||||||
padding: var(--spacing);
|
padding: var(--spacing);
|
||||||
|
|
||||||
.Table .TableHead {
|
.Table .TableHead {
|
||||||
background-color: $contentColor;
|
|
||||||
border-bottom: 1px solid $borderFaintColor;
|
border-bottom: 1px solid $borderFaintColor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./editable-list";
|
export * from "./editable-list";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./error-boundary";
|
export * from "./error-boundary";
|
||||||
|
|||||||
@ -209,4 +209,4 @@ export class FilePicker extends React.Component<Props> {
|
|||||||
return <Icon material="error" title={this.errorText}></Icon>;
|
return <Icon material="error" title={this.errorText}></Icon>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./file-picker";
|
export * from "./file-picker";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./icon";
|
export * from "./icon";
|
||||||
|
|||||||
@ -54,4 +54,4 @@ export class SearchInputUrl extends React.Component<Props> {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./item-list-layout";
|
export * from "./item-list-layout";
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import "./item-list-layout.scss";
|
|||||||
import groupBy from "lodash/groupBy";
|
import groupBy from "lodash/groupBy";
|
||||||
|
|
||||||
import React, { ReactNode } from "react";
|
import React, { ReactNode } from "react";
|
||||||
import { computed, observable, reaction, toJS } from "mobx";
|
import { computed, IReactionDisposer, observable, reaction, toJS } from "mobx";
|
||||||
import { disposeOnUnmount, observer } from "mobx-react";
|
import { disposeOnUnmount, observer } from "mobx-react";
|
||||||
import { ConfirmDialog, ConfirmDialogParams } from "../confirm-dialog";
|
import { ConfirmDialog, ConfirmDialogParams } from "../confirm-dialog";
|
||||||
import { Table, TableCell, TableCellProps, TableHead, TableProps, TableRow, TableRowProps, TableSortCallback } from "../table";
|
import { Table, TableCell, TableCellProps, TableHead, TableProps, TableRow, TableRowProps, TableSortCallback } from "../table";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./kube-object-status-icon";
|
export * from "./kube-object-status-icon";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./kubeconfig-dialog";
|
export * from "./kubeconfig-dialog";
|
||||||
|
|||||||
@ -46,4 +46,4 @@ describe("<MainLayoutHeader />", () => {
|
|||||||
|
|
||||||
expect(getByText("minikube")).toBeInTheDocument();
|
expect(getByText("minikube")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -34,4 +34,4 @@ export class LoginLayout extends React.Component<Props> {
|
|||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,4 +4,4 @@ export const SidebarContext = React.createContext<SidebarContextValue>({ pinned:
|
|||||||
|
|
||||||
export type SidebarContextValue = {
|
export type SidebarContextValue = {
|
||||||
pinned: boolean;
|
pinned: boolean;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./line-progress";
|
export * from "./line-progress";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./markdown-viewer";
|
export * from "./markdown-viewer";
|
||||||
|
|||||||
@ -34,4 +34,4 @@ export class MarkdownViewer extends Component<Props> {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./radio";
|
export * from "./radio";
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
export * from "./resource-metrics";
|
export * from "./resource-metrics";
|
||||||
export * from "./resource-metrics-text";
|
export * from "./resource-metrics-text";
|
||||||
|
|||||||
@ -3,11 +3,9 @@
|
|||||||
|
|
||||||
html {
|
html {
|
||||||
$menuBackgroundColor: $contentColor;
|
$menuBackgroundColor: $contentColor;
|
||||||
$menuSelectedOptionBgc: $layoutBackground;
|
|
||||||
|
|
||||||
--select-menu-bgc: #{$menuBackgroundColor};
|
--select-menu-bgc: #{$menuBackgroundColor};
|
||||||
--select-menu-border-color: #{$halfGray};
|
--select-menu-border-color: #{$halfGray};
|
||||||
--select-option-selected-bgc: #{$menuSelectedOptionBgc};
|
|
||||||
--select-option-selected-color: #{$selectOptionHoveredColor};
|
--select-option-selected-color: #{$selectOptionHoveredColor};
|
||||||
--select-option-focused-bgc: #{$colorInfo};
|
--select-option-focused-bgc: #{$colorInfo};
|
||||||
--select-option-focused-color: #{$textColorAccent};
|
--select-option-focused-color: #{$textColorAccent};
|
||||||
@ -95,7 +93,7 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&--is-selected {
|
&--is-selected {
|
||||||
background: var(--select-option-selected-bgc);
|
background: var(--menuSelectedOptionBgc);
|
||||||
color: var(--select-option-selected-color);
|
color: var(--select-option-selected-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +146,6 @@ html {
|
|||||||
&.theme-light {
|
&.theme-light {
|
||||||
--select-menu-bgc: white;
|
--select-menu-bgc: white;
|
||||||
--select-option-selected-color: $textColorSecondary;
|
--select-option-selected-color: $textColorSecondary;
|
||||||
--select-option-selected-bgc: $textColorSecondary;
|
|
||||||
|
|
||||||
.Select {
|
.Select {
|
||||||
&__multi-value {
|
&__multi-value {
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./slider";
|
export * from "./slider";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./status-brick";
|
export * from "./status-brick";
|
||||||
|
|||||||
@ -19,4 +19,4 @@ export class StatusBrick extends React.Component<StatusBrickProps> {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./virtual-list";
|
export * from "./virtual-list";
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./wizard";
|
export * from "./wizard";
|
||||||
|
|||||||
@ -16,4 +16,4 @@ export function useInterval(callback: () => void, delay: number) {
|
|||||||
|
|
||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
}, [delay]);
|
}, [delay]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,4 +2,4 @@ import { useEffect } from "react";
|
|||||||
|
|
||||||
export function useOnUnmount(callback: () => void) {
|
export function useOnUnmount(callback: () => void) {
|
||||||
useEffect(() => callback, []);
|
useEffect(() => callback, []);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,4 +10,4 @@ export function useStorage<T>(key: string, initialValue?: T, options?: IStorageH
|
|||||||
};
|
};
|
||||||
|
|
||||||
return [storageValue, setValue] as [T, (value: T) => void];
|
return [storageValue, setValue] as [T, (value: T) => void];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,4 +28,4 @@ export function bindEvents() {
|
|||||||
subscribeToBroadcast("renderer:reload", () => {
|
subscribeToBroadcast("renderer:reload", () => {
|
||||||
location.reload();
|
location.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user