diff --git a/client/package-lock.json b/client/package-lock.json
index 921549a..907732e 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1914,6 +1914,11 @@
"resolved": "https://nexus.corp.indeed.com/repository/npm/@types/stack-utils/-/stack-utils-1.0.1.tgz",
"integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw=="
},
+ "@types/yamljs": {
+ "version": "0.2.31",
+ "resolved": "https://nexus.corp.indeed.com/repository/npm/@types/yamljs/-/yamljs-0.2.31.tgz",
+ "integrity": "sha512-QcJ5ZczaXAqbVD3o8mw/mEBhRvO5UAdTtbvgwL/OgoWubvNBh6/MxLBAigtcgIFaq3shon9m3POIxQaLQt4fxQ=="
+ },
"@types/yargs": {
"version": "13.0.9",
"resolved": "https://nexus.corp.indeed.com/repository/npm/@types/yargs/-/yargs-13.0.9.tgz",
diff --git a/client/package.json b/client/package.json
index de24361..ff04d7b 100644
--- a/client/package.json
+++ b/client/package.json
@@ -12,6 +12,7 @@
"@types/react-dom": "^16.9.8",
"@types/react-modal": "1.6.8",
"@types/react-select": "^3.0.16",
+ "@types/yamljs": "^0.2.31",
"ansi-to-react": "^5.1.1",
"humanize-duration": "^3.23.1",
"js-base64": "^2.6.4",
diff --git a/client/src/components/error.tsx b/client/src/components/error.tsx
index bd7f459..31e945a 100644
--- a/client/src/components/error.tsx
+++ b/client/src/components/error.tsx
@@ -1,7 +1,7 @@
import './error.scss';
import React from 'react';
-const Error = ({messages}: {messages: [string]}) => (
+const Error = ({messages}: {messages: string[]}) => (
{messages.map((x, i) => (
{x}
diff --git a/client/src/components/eventsPanel.tsx b/client/src/components/eventsPanel.tsx
index 7c3ae86..cf49a50 100644
--- a/client/src/components/eventsPanel.tsx
+++ b/client/src/components/eventsPanel.tsx
@@ -4,28 +4,13 @@ import {TableBody} from './listViewHelpers';
import log from '../utils/log';
import ResourceSvg from '../art/resourceSvg';
import Sorter, {sortByDate, SortInfo} from './sorter';
+import { K8sEvent, InvolvedObject } from '../utils/types';
-type Metadata = {
- name: string;
- creationTimestamp: number;
-}
-type InvolvedObject = {
- kind: string;
- namespace: string;
- name: string;
-}
-type Event = {
- metadata: Metadata;
- involvedObject: InvolvedObject;
- message: string;
- reason: string;
- type: string;
-}
type EventsPanelProps = {
- items: Event[];
- filter: React.ReactNode;
+ items?: K8sEvent[];
+ filter?: React.ReactNode;
shortList?: boolean;
- sort: SortInfo;
+ sort?: SortInfo;
}
export default function EventsPanel({items, filter, shortList, sort} : EventsPanelProps) {
@@ -59,17 +44,17 @@ export default function EventsPanel({items, filter, shortList, sort} : EventsPan
filter={filter}
colSpan={shortList ? 4 : 5}
sort={sort}
- row={(event: Event) => (
+ row={(event) => (
|
- {event.involvedObject.kind}
+ {event.involvedObject!.kind}
|
{!shortList && (
- {getName(event.involvedObject)} |
+ {getName(event.involvedObject!)} |
)}
{fromNow(event.metadata.creationTimestamp)} |
{event.reason} |
@@ -85,11 +70,11 @@ export default function EventsPanel({items, filter, shortList, sort} : EventsPan
function getName({kind, namespace, name} : InvolvedObject) {
const text = namespace ? `${namespace}:${name}` : name;
- const href = getHref({kind, namespace, name});
+ const href = getHref(kind, namespace, name);
return href ? ({text}) : text;
}
-function getHref({kind, namespace, name} : InvolvedObject) {
+function getHref(kind: string, namespace: string, name: string) {
switch (kind) {
case 'ClusterRole': return `/#!clusterrole/${name}`;
case 'ClusterRoleBinding': return `/#!clusterrolebinding/${name}`;
@@ -113,8 +98,8 @@ function getHref({kind, namespace, name} : InvolvedObject) {
}
}
-function sortByName(event: Event) {
- return `${event.involvedObject.namespace}:${event.involvedObject.name}`;
+function sortByName(event: K8sEvent) {
+ return `${event.involvedObject!.namespace}:${event.involvedObject!.name}`;
}
function getTypeClass(type: string) {
diff --git a/client/src/components/filter.tsx b/client/src/components/filter.tsx
index 32989ac..a03984c 100644
--- a/client/src/components/filter.tsx
+++ b/client/src/components/filter.tsx
@@ -6,7 +6,7 @@ type FilterProps = {
text: string;
filter: string;
onChange: (value: string) => void;
- onNamespaceChange?: Function;
+ onNamespaceChange?: (namespace: string) => void;
}
const Filter = ({text, filter, onChange, onNamespaceChange}: FilterProps) => (
diff --git a/client/src/components/itemHeader.tsx b/client/src/components/itemHeader.tsx
index 5537e44..f2e7579 100644
--- a/client/src/components/itemHeader.tsx
+++ b/client/src/components/itemHeader.tsx
@@ -3,7 +3,7 @@ import Base from './base';
interface ItemHeaderProps {
title: string[];
- ready: boolean;
+ ready?: boolean;
}
export default class ItemHeader extends Base {
diff --git a/client/src/components/listViewHelpers.tsx b/client/src/components/listViewHelpers.tsx
index 932caad..7784d6d 100644
--- a/client/src/components/listViewHelpers.tsx
+++ b/client/src/components/listViewHelpers.tsx
@@ -7,6 +7,14 @@ import Sorter, {sortByDate, SortInfo} from './sorter';
import ResourceSvg from '../art/resourceSvg';
import {TODO} from '../utils/types';
+type TableBodyProps = {
+ items?: T[] | null;
+ filter: TODO;
+ colSpan: number;
+ sort?: SortInfo;
+ row: (item: T) => ReactNode;
+}
+
export function objectMap(items: {[key: string]: string} = {}) {
return Object.entries(items).map(([key, value]) => {
const substrValue = value.length <= 50 ? value : `${value.substr(0, 50)}...`;
@@ -30,14 +38,6 @@ export function objectMap(items: {[key: string]: string} = {}) {
});
}
-type TableBodyProps = {
- items?: T[] | null;
- filter: TODO;
- colSpan: number;
- sort: SortInfo;
- row: (item: T) => ReactNode;
-}
-
export function TableBody({items, filter, colSpan, sort, row}: TableBodyProps) {
if (items && sort) {
const {field, direction} = sort;
diff --git a/client/src/components/nodeCpuChart.tsx b/client/src/components/nodeCpuChart.tsx
index 0b175c2..f103961 100644
--- a/client/src/components/nodeCpuChart.tsx
+++ b/client/src/components/nodeCpuChart.tsx
@@ -3,9 +3,9 @@ import React from 'react';
import Chart from './chart';
import LoadingChart from './loadingChart';
import {parseCpu, TO_ONE_CPU} from '../utils/unitHelpers';
-import {TODO} from '../utils/types';
+import {Node, Metrics} from '../utils/types';
-export default function NodeCpuChart({items, metrics}: {items: TODO[], metrics: TODO[]}) {
+export default function NodeCpuChart({items, metrics}: {items?: Node[], metrics?: _.Dictionary}) {
const totals = getNodeCpuTotals(items, metrics);
return (
@@ -21,7 +21,7 @@ export default function NodeCpuChart({items, metrics}: {items: TODO[], metrics:
);
}
-function getNodeCpuTotals(items: TODO[], metrics: TODO[]) {
+function getNodeCpuTotals(items?: Node[], metrics?: _.Dictionary) {
if (!items || !metrics) return null;
const metricValues = Object.values(metrics);
diff --git a/client/src/components/nodeRamChart.tsx b/client/src/components/nodeRamChart.tsx
index 2c4d2c2..9f84607 100644
--- a/client/src/components/nodeRamChart.tsx
+++ b/client/src/components/nodeRamChart.tsx
@@ -3,9 +3,9 @@ import React from 'react';
import Chart from './chart';
import LoadingChart from './loadingChart';
import {parseRam, TO_GB} from '../utils/unitHelpers';
-import {TODO} from '../utils/types';
+import {Node, Metrics} from '../utils/types';
-export default function NodeRamChart({items, metrics}: {items: TODO[], metrics: TODO[]}) {
+export default function NodeRamChart({items, metrics}: {items?: Node[], metrics?: _.Dictionary}) {
const totals = getNodeRamTotals(items, metrics);
return (
@@ -20,7 +20,7 @@ export default function NodeRamChart({items, metrics}: {items: TODO[], metrics:
);
}
-function getNodeRamTotals(items: TODO[], metrics: TODO[]) {
+function getNodeRamTotals(items?: Node[], metrics?: _.Dictionary
) {
if (!items || !metrics) return null;
const metricValues = Object.values(metrics);
diff --git a/client/src/components/saveButton.tsx b/client/src/components/saveButton.tsx
index bc719de..e769eec 100644
--- a/client/src/components/saveButton.tsx
+++ b/client/src/components/saveButton.tsx
@@ -3,17 +3,18 @@ import Base from './base';
import Button from './button';
import EditorModal from '../views/editorModal';
import EditSvg from '../art/editSvg';
+import { ApiItem } from '../utils/types';
-interface SaveButtonProps {
- onSave: Function
- item: {}
+interface SaveButtonProps> {
+ item: T;
+ onSave: (item: T) => Promise;
}
interface SaveButtonStates {
showEditor: boolean;
}
-export default class SaveButton extends Base {
+export default class SaveButton> extends Base, SaveButtonStates> {
render() {
const {onSave, item} = this.props;
const {showEditor = null} = this.state || {};
diff --git a/client/src/components/sorter.tsx b/client/src/components/sorter.tsx
index b4faf70..c12e27d 100644
--- a/client/src/components/sorter.tsx
+++ b/client/src/components/sorter.tsx
@@ -15,7 +15,7 @@ export interface SortInfo {
interface SorterProps {
field: TODO;
- sort: {
+ sort?: {
field: string,
direction: Direction,
onSort: Function,
@@ -28,7 +28,7 @@ interface SorterStates {
type SortCallback = (item: TODO) => void;
-export function defaultSortInfo(target: Component | SortCallback, field = 'metadata.name', direction: Direction = 'asc'): SortInfo {
+export function defaultSortInfo(target: Component | SortCallback, field: TODO = 'metadata.name', direction: Direction = 'asc'): SortInfo {
return {
field,
direction,
@@ -79,11 +79,11 @@ export default class Sorter extends Base {
isUpSelected() {
const {sort} = this.props;
- return (this.isSelected() && sort.direction === 'asc');
+ return (this.isSelected() && sort!.direction === 'asc');
}
isDownSelected() {
const {sort} = this.props;
- return (this.isSelected() && sort.direction === 'desc');
+ return (this.isSelected() && sort!.direction === 'desc');
}
}
diff --git a/client/src/services/api.ts b/client/src/services/api.ts
index 9f0cfa3..d324b0e 100644
--- a/client/src/services/api.ts
+++ b/client/src/services/api.ts
@@ -102,11 +102,11 @@ function metricsFactory() {
return {
nodes: (cb: DataCallback) => metrics('/apis/metrics.k8s.io/v1beta1/nodes', cb),
node: (name: string, cb: DataCallback) => metrics(`/apis/metrics.k8s.io/v1beta1/nodes/${name}`, cb),
- pods: (namespace: string, cb: DataCallback) => metrics(url(namespace), cb),
+ pods: (namespace: string | undefined, cb: DataCallback) => metrics(url(namespace), cb),
pod: (namespace: string, name: string, cb: DataCallback) => metrics(`/apis/metrics.k8s.io/v1beta1/namespaces/${namespace}/pods/${name}`, cb),
};
- function url(namespace: string) {
+ function url(namespace?: string) {
return namespace ? `/apis/metrics.k8s.io/v1beta1/namespaces/${namespace}/pods` : '/apis/metrics.k8s.io/v1beta1/pods';
}
}
diff --git a/client/src/services/apiProxy.ts b/client/src/services/apiProxy.ts
index 40f2a54..5e1d1ab 100644
--- a/client/src/services/apiProxy.ts
+++ b/client/src/services/apiProxy.ts
@@ -74,7 +74,7 @@ export function apiFactoryWithNamespace>(group: stri
const apiRoot = getApiRoot(group, version);
return {
resource: {group, resource},
- list: (namespace: string, cb: StreamCallback, errCb?: ErrorCallback) => streamResults(url(namespace), cb, errCb),
+ list: (namespace: string | undefined, cb: StreamCallback, errCb?: ErrorCallback) => streamResults(url(namespace), cb, errCb),
get: (namespace: string, name: string, cb: StreamCallback, errCb?: ErrorCallback) => streamResult(url(namespace), name, cb, errCb),
post: (body: any) => post(url(body.metadata.namespace), body),
put: (body: any) => put(`${url(body.metadata.namespace)}/${body.metadata.name}`, body),
@@ -82,7 +82,7 @@ export function apiFactoryWithNamespace>(group: stri
scale: includeScale ? apiScaleFactory(apiRoot, resource) : undefined,
};
- function url(namespace: string) {
+ function url(namespace?: string) {
return namespace ? `${apiRoot}/namespaces/${namespace}/${resource}` : `${apiRoot}/${resource}`;
}
}
diff --git a/client/src/services/docs.js b/client/src/services/docs.ts
similarity index 64%
rename from client/src/services/docs.js
rename to client/src/services/docs.ts
index a6692cf..952917c 100644
--- a/client/src/services/docs.js
+++ b/client/src/services/docs.ts
@@ -1,14 +1,15 @@
import Swagger from 'swagger-parser';
import apis from './api';
+import { TODO } from '../utils/types';
-let docsPromise;
+let docsPromise: Promise;
async function getDocs() {
const docs = await apis.swagger();
return Swagger.dereference(docs);
}
-export default async function getDocDefinitions(apiVersion, kind) {
+export default async function getDocDefinitions(apiVersion: string, kind: string) {
if (!docsPromise) {
docsPromise = getDocs(); // Don't wait here. Just kick off the request
}
@@ -22,10 +23,10 @@ export default async function getDocDefinitions(apiVersion, kind) {
}
return Object.values(definitions)
- .filter(x => !!x['x-kubernetes-group-version-kind'])
- .find(x => x['x-kubernetes-group-version-kind'].some(comparer));
+ .filter((x: TODO) => !!x['x-kubernetes-group-version-kind'])
+ .find((x: TODO) => x['x-kubernetes-group-version-kind'].some(comparer));
- function comparer(info) {
+ function comparer(info: TODO) {
return info.group === group
&& info.version === version
&& info.kind === kind;
diff --git a/client/src/utils/filterHelper.ts b/client/src/utils/filterHelper.ts
index 0c7604f..4b4eb10 100644
--- a/client/src/utils/filterHelper.ts
+++ b/client/src/utils/filterHelper.ts
@@ -1,4 +1,4 @@
-import {TODO} from './types';
+import {ApiItem} from './types';
export default function test(filter = '', ...values: string[]) {
const value = filter.toLowerCase();
@@ -7,8 +7,8 @@ export default function test(filter = '', ...values: string[]) {
.some(x => x.toLowerCase().includes(value));
}
-export function filterByOwner(items: TODO[], owner: TODO) {
- if (!items || !owner) return null;
+export function filterByOwner>(items?: T[], owner?: ApiItem): T[] | undefined {
+ if (!items || !owner) return undefined;
const {uid} = owner.metadata;
@@ -20,15 +20,15 @@ export function filterByOwner(items: TODO[], owner: TODO) {
});
}
-export function filterByOwners(items: TODO[], owners: TODO) {
- if (!items || !owners) return null;
+export function filterByOwners>(items?: T[], owners?: ApiItem[]): T[] | undefined {
+ if (!items || !owners) return undefined;
- const uids = owners.map((x: any) => x.metadata.uid);
+ const uidList = owners.map(x => x.metadata.uid);
return items.filter((x) => {
- if (x.involvedObject && uids.includes(x.involvedObject.uid)) return true;
+ if (x.involvedObject && uidList.includes(x.involvedObject.uid)) return true;
const {ownerReferences} = x.metadata;
- return ownerReferences && ownerReferences.some((y: {uid: string}) => uids.includes(y.uid));
+ return ownerReferences && ownerReferences.some((y: {uid: string}) => uidList.includes(y.uid));
});
}
diff --git a/client/src/utils/metricsHelpers.tsx b/client/src/utils/metricsHelpers.tsx
index 6787d39..86e0320 100644
--- a/client/src/utils/metricsHelpers.tsx
+++ b/client/src/utils/metricsHelpers.tsx
@@ -1,8 +1,10 @@
import _ from 'lodash';
import {parseRam, parseCpu} from './unitHelpers';
-import {TODO, Pod, Node, Metrics} from './types';
+import {TODO, ApiItem, Pod, Node, Metrics, MetricsUsage} from './types';
-export default function getMetrics(items?: Pod[], metrics?: Metrics[]) {
+type ResourceType = 'cpu' | 'memory'
+
+export default function getMetrics(items?: ApiItem[], metrics?: Metrics[]) {
if (!items || !metrics) return undefined;
const names = _.map(items, x => x.metadata.name);
@@ -13,7 +15,7 @@ export default function getMetrics(items?: Pod[], metrics?: Metrics[]) {
// Node helpers
-export function getNodeResourceValue(node: Node | undefined, pods: Pod[] | undefined, resource: string, type: string, phases: string[]) {
+export function getNodeResourceValue(node: Node | undefined, pods: Pod[] | undefined, resource: ResourceType, type: string, phases: string[]) {
if (!node || !pods) return null;
return _(pods)
@@ -22,23 +24,23 @@ export function getNodeResourceValue(node: Node | undefined, pods: Pod[] | undef
.sumBy(x => getPodResourceValue(x, resource, type));
}
-export function getNodeResourcePercent(node: TODO, pods: TODO, resource: string, type: string) {
+export function getNodeResourcePercent(node: Node, pods: Pod[], resource: ResourceType, type: string) {
const used = getNodeResourceValue(node, pods, resource, type, ['Running']);
const available = getNodeResourcesAvailable(node, resource);
return used && available ? used / available : null;
}
-export function getNodeUsagePercent(node: TODO, metrics: TODO, resource: string) {
+export function getNodeUsagePercent(node: Node, metrics: _.Dictionary, resource: ResourceType) {
const used = getNodeUsage(node, metrics, resource);
const available = getNodeResourcesAvailable(node, resource);
return used && available ? used / available : null;
}
-export function getNodeResourcesAvailable(node: TODO, resource: string) {
+export function getNodeResourcesAvailable(node: Node, resource: ResourceType) {
return node ? parse(resource, node.status.capacity) : null;
}
-export function getNodeUsage(node: TODO, metrics: TODO, resource: string) {
+export function getNodeUsage(node: Node, metrics: _.Dictionary, resource: ResourceType) {
if (!node || !metrics) return null;
const result = metrics[node.metadata.name];
@@ -47,26 +49,27 @@ export function getNodeUsage(node: TODO, metrics: TODO, resource: string) {
// Pod helpers
-export function getPodResourcePercent(item: TODO, metrics: TODO, resource: string, type: string) {
- const actual = getPodUsage(item, metrics, resource);
- const request = getPodResourceValue(item, resource, type);
+export function getPodResourcePercent(pod: Pod, metrics: _.Dictionary, resource: ResourceType, type: string) {
+ const actual = getPodUsage(pod, metrics, resource);
+ const request = getPodResourceValue(pod, resource, type);
return actual ? actual / request : null;
}
-export function getPodUsage(pod: TODO, metrics: TODO, resource: string) {
+export function getPodUsage(pod: Pod, metrics: _.Dictionary, resource: ResourceType) {
if (!pod || !metrics) return null;
const metric = metrics[pod.metadata.name] || {};
- return _.sumBy(metric.containers, (x: TODO) => parse(resource, x.usage));
+ return _.sumBy(metric.containers, x => parse(resource, x.usage));
}
-export function getPodResourceValue(pod: TODO, resource: string, type: string) {
+export function getPodResourceValue(pod: TODO, resource: ResourceType, type: string) {
return _(pod.spec.containers)
.filter(x => x.resources && x.resources[type])
.sumBy(x => parse(resource, x.resources[type]));
}
-function parse(resource: string, target: {[key: string]: string}) {
+function parse(resource: ResourceType, target: MetricsUsage) {
const parser = resource === 'cpu' ? parseCpu : parseRam;
+ // @ts-ignore
return parser(target[resource]);
}
diff --git a/client/src/utils/nodeHelpers.ts b/client/src/utils/nodeHelpers.ts
index 3f76b91..ead7d46 100644
--- a/client/src/utils/nodeHelpers.ts
+++ b/client/src/utils/nodeHelpers.ts
@@ -1,12 +1,12 @@
-import {TODO} from './types';
+import {Node} from './types';
/**
* @param {*status* object with a status field (most likely the row from the TableBody)}
* @returns the status text, as defined in https://kubernetes.io/docs/concepts/architecture/nodes/#condition
*/
-function getReadyStatus({status}: TODO) {
- if (!status.conditions) return null;
- const ready = status.conditions.find((y: {type: string}) => y.type === 'Ready');
+function getReadyStatus({status}: Node) {
+ if (!status.conditions) return undefined;
+ const ready = status.conditions.find(y => y.type === 'Ready');
return ready && ready.status;
}
diff --git a/client/src/utils/types.ts b/client/src/utils/types.ts
index 2175963..3dad45f 100644
--- a/client/src/utils/types.ts
+++ b/client/src/utils/types.ts
@@ -2,15 +2,31 @@ export type TODO = any;
export type ApiItem = {
kind: string;
+ apiVersion: string;
metadata: Metadata;
spec: TSpec;
- status: TStatus
+ status: TStatus;
+ involvedObject?: InvolvedObject;
+}
+
+export interface InvolvedObject {
+ uid: string;
+ kind: string;
+ namespace: string;
+ name: string;
}
interface Metadata {
uid: string;
resourceVersion: string;
+ creationTimestamp: number;
name: string;
+ labels: {[name: string]: string};
+ ownerReferences?: {
+ uid: string;
+ kind: string;
+ name: string;
+ }[];
}
interface Container {
@@ -26,8 +42,28 @@ interface Container {
}
}
+interface Condition {
+ type: string;
+ status: string;
+ lastTransitionTime: number;
+ reason: string;
+ message: string;
+}
+
+export interface MetricsUsage {
+ cpu?: string;
+ memory?: string;
+}
+
export interface Metrics extends ApiItem {
containers: Container[];
+ resources?: {
+ requests?: {
+ cpu?: string;
+ memory?: string;
+ }
+ }
+ usage: MetricsUsage
}
interface NamespaceStatus {
@@ -37,20 +73,50 @@ interface NamespaceStatus {
export interface Namespace extends ApiItem {
}
-export interface Node extends ApiItem {
+interface NodeSpec {
+ taints: {[name: string]: string}
+}
+
+export interface NodeStatus {
+ capacity: {
+ cpu?: string;
+ memory?: string;
+ }
+ conditions: Condition[];
+ nodeInfo: {
+ kernelVersion: string;
+ osImage: string;
+ operatingSystem: string;
+ architecture: string;
+ containerRuntimeVersion: string;
+ kubeletVersion: string;
+ kubeProxyVersion: string;
+ }
+}
+
+export interface Node extends ApiItem {
}
-export interface K8sEvent extends ApiItem{
+export interface K8sEvent extends ApiItem {
+ type: string;
+ reason: string;
+ message: string;
}
interface PodSpec {
nodeName: string;
containers: Container[];
+ nodeSelector?: {[key: string]: string};
}
interface PodStatus {
phase: string;
+ hostIP: string;
+ podIP: string;
+ qosClass: string;
+ message: string;
+ conditions?: Condition[];
}
export interface Pod extends ApiItem{
diff --git a/client/src/views/editorModal.js b/client/src/views/editorModal.tsx
similarity index 88%
rename from client/src/views/editorModal.js
rename to client/src/views/editorModal.tsx
index 8aaf02b..1c38ac6 100644
--- a/client/src/views/editorModal.js
+++ b/client/src/views/editorModal.tsx
@@ -8,9 +8,22 @@ import Doc from '../components/doc';
import getDocDefinitions from '../services/docs';
import LightBulbSvg from '../art/lightBulbSvg';
import EditSvg from '../art/editSvg';
+import { ApiItem, TODO } from '../utils/types';
-export default class EditorModal extends Base {
- state = {
+interface Props> {
+ body: T;
+ onSave: (item: T) => Promise;
+ onRequestClose: () => void;
+}
+
+type State = {
+ showDocs: boolean;
+ yaml?: string;
+ properties?: TODO;
+}
+
+export default class EditorModal> extends Base, State> {
+ state: State = {
showDocs: false,
};
@@ -18,7 +31,7 @@ export default class EditorModal extends Base {
this.findDocs(this.props.body);
}
- async onEdit(yaml) {
+ async onEdit(yaml: string) {
this.setState({yaml});
try {
@@ -39,10 +52,10 @@ export default class EditorModal extends Base {
if (shouldClose) this.close();
}
- async findDocs(body) {
+ async findDocs(body: T) {
if (!body || !body.apiVersion || !body.kind) return;
- const result = await getDocDefinitions(body.apiVersion, body.kind);
+ const result: TODO = await getDocDefinitions(body.apiVersion, body.kind);
if (!result) return;
this.setState({properties: result.properties});
diff --git a/client/src/views/exec.js b/client/src/views/exec.js
index f2eec26..b159405 100644
--- a/client/src/views/exec.js
+++ b/client/src/views/exec.js
@@ -30,7 +30,7 @@ export default class Exec extends Base {
const {namespace, name} = this.props;
const exec = api.exec(namespace, name, container, items => this.onData(items));
- this.socket = exec.getSocket(); // TODO: this won't work if the socket failes
+ this.socket = exec.getSocket(); // TODO: this won't work if the socket fails
this.registerApi({cancel: exec.cancel});
if (this.xterm) this.xterm.reset();
diff --git a/client/src/views/node.js b/client/src/views/node.tsx
similarity index 87%
rename from client/src/views/node.js
rename to client/src/views/node.tsx
index dcde9d0..1370448 100644
--- a/client/src/views/node.js
+++ b/client/src/views/node.tsx
@@ -8,7 +8,7 @@ import Loading from '../components/loading';
import LoadingChart from '../components/loadingChart';
import MetadataFields from '../components/metadataFields';
import PodsPanel from '../components/podsPanel';
-import {defaultSortInfo} from '../components/sorter';
+import {defaultSortInfo, SortInfo} from '../components/sorter';
import Field from '../components/field';
import ChartsContainer from '../components/chartsContainer';
import NodeCpuChart from '../components/nodeCpuChart';
@@ -17,9 +17,22 @@ import PodStatusChart from '../components/podStatusChart';
import PodCpuChart from '../components/podCpuChart';
import PodRamChart from '../components/podRamChart';
import getMetrics from '../utils/metricsHelpers';
+import {Node, Pod, Metrics, TODO} from '../utils/types';
-export default class Node extends Base {
- state = {
+type Props = {
+ name: string;
+}
+
+type State = {
+ podsSort: SortInfo;
+ item?: Node;
+ metrics?: Metrics[];
+ pods?: Pod[];
+ podMetrics?: Metrics[];
+}
+
+export default class NodeView extends Base {
+ state: State = {
podsSort: defaultSortInfo(x => this.setState({podsSort: x})),
};
@@ -29,8 +42,8 @@ export default class Node extends Base {
this.registerApi({
item: api.node.get(name, item => this.setState({item})),
metrics: api.metrics.node(name, metrics => this.setState({metrics})),
- pods: api.pod.list(null, pods => this.setState({pods})),
- podMetrics: api.metrics.pods(null, podMetrics => this.setState({podMetrics})),
+ pods: api.pod.list(undefined, pods => this.setState({pods})),
+ podMetrics: api.metrics.pods(undefined, podMetrics => this.setState({podMetrics})),
});
}
@@ -54,7 +67,13 @@ export default class Node extends Base {
)}
Uptime
+
+ {/*
+ // @ts-ignore */}
+
+ {/*
+ // @ts-ignore */}
@@ -119,18 +138,14 @@ export default class Node extends Base {
}
}
-/**
- * Render "taints" divs from the node spec
- *
- * @param spec spec from a node item
- */
-function getTaints({spec}) {
- return _.map(spec.taints, ({key, effect}) => (
+
+function getTaints({spec}: Node) {
+ return _.map(spec.taints, ({key, effect}: TODO) => (
{key} • {effect}
));
}
-function getUptime({status}) {
+function getUptime({status}: Node) {
const ready = status.conditions.find(y => y.type === 'Ready');
if (!ready) return 'N/A';
diff --git a/client/src/views/nodes.js b/client/src/views/nodes.tsx
similarity index 81%
rename from client/src/views/nodes.js
rename to client/src/views/nodes.tsx
index a7413df..64947a2 100644
--- a/client/src/views/nodes.js
+++ b/client/src/views/nodes.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import Base from '../components/base';
import ChartsContainer from '../components/chartsContainer';
import Filter from '../components/filter';
-import {defaultSortInfo} from '../components/sorter';
+import {defaultSortInfo, SortInfo} from '../components/sorter';
import NodeStatusChart from '../components/nodeStatusChart';
import api from '../services/api';
import test from '../utils/filterHelper';
@@ -11,9 +11,18 @@ import getReadyStatus from '../utils/nodeHelpers';
import NodeCpuChart from '../components/nodeCpuChart';
import NodeRamChart from '../components/nodeRamChart';
import getMetrics from '../utils/metricsHelpers';
+import { Node, Metrics, Pod } from '../utils/types';
-export default class Nodes extends Base {
- state = {
+type State = {
+ filter: string;
+ sort: SortInfo;
+ items?: Node[];
+ metrics?: Metrics[];
+ pods?: Pod[];
+};
+
+export default class Nodes extends Base<{}, State> {
+ state: State = {
filter: '',
sort: defaultSortInfo(this, getReadyStatus, 'asc'),
};
@@ -22,7 +31,7 @@ export default class Nodes extends Base {
this.registerApi({
items: api.node.list(items => this.setState({items})),
metrics: api.metrics.nodes(metrics => this.setState({metrics})),
- pods: api.pod.list(null, pods => this.setState({pods})),
+ pods: api.pod.list(undefined, pods => this.setState({pods})),
});
}
@@ -57,8 +66,8 @@ export default class Nodes extends Base {
}
}
-function filterNodes(items, filter) {
- if (!items) return null;
+function filterNodes(items?: Node[], filter?: string) {
+ if (!items) return undefined;
return items.filter((x) => {
const labels = x.metadata.labels || {};
diff --git a/client/src/views/pod.js b/client/src/views/pod.tsx
similarity index 93%
rename from client/src/views/pod.js
rename to client/src/views/pod.tsx
index 7f64076..c6b802b 100644
--- a/client/src/views/pod.js
+++ b/client/src/views/pod.tsx
@@ -19,10 +19,22 @@ import getMetrics from '../utils/metricsHelpers';
import PodCpuChart from '../components/podCpuChart';
import PodRamChart from '../components/podRamChart';
import ChartsContainer from '../components/chartsContainer';
+import { Pod, Metrics, K8sEvent } from '../utils/types';
+
+type Props = {
+ namespace: string;
+ name: string;
+}
+
+type State = {
+ item?: Pod;
+ metrics?: Metrics[];
+ events?: K8sEvent[];
+}
const service = api.pod;
-export default class Pod extends Base {
+export default class PodView extends Base {
componentDidMount() {
const {namespace, name} = this.props;
@@ -39,6 +51,7 @@ export default class Pod extends Base {
const errors = getErrors(item);
const filteredEvents = filterByOwner(events, item);
+ // @ts-ignore
const filteredMetrics = getMetrics(item && [item], metrics && [metrics]);
return (
@@ -56,7 +69,7 @@ export default class Pod extends Base {
service.put(x)}
/>
@@ -125,10 +138,10 @@ export default class Pod extends Base {
}
}
-function getErrors(item) {
+function getErrors(item?: Pod) {
if (!item) return [];
if (item.status.message) return [item.status.message];
if (item.status.conditions) return item.status.conditions.map(x => x.message).filter(x => !!x);
- return null;
+ return undefined;
}
diff --git a/client/src/views/pods.js b/client/src/views/pods.tsx
similarity index 83%
rename from client/src/views/pods.js
rename to client/src/views/pods.tsx
index e2a848c..a6ed3dd 100644
--- a/client/src/views/pods.js
+++ b/client/src/views/pods.tsx
@@ -7,20 +7,29 @@ import PodCpuChart from '../components/podCpuChart';
import PodRamChart from '../components/podRamChart';
import PodsPanel from '../components/podsPanel';
import PodStatusChart from '../components/podStatusChart';
-import {defaultSortInfo} from '../components/sorter';
+import {defaultSortInfo, SortInfo} from '../components/sorter';
import getMetrics from '../utils/metricsHelpers';
import ChartsContainer from '../components/chartsContainer';
+import {Pod, Metrics} from '../utils/types';
-export default class Pods extends Base {
- state = {
+type State = {
+ namespace: string;
+ filter: string;
+ sort: SortInfo;
+ items?: Pod[];
+ metrics?: Metrics[];
+}
+
+export default class Pods extends Base<{}, State> {
+ state: State = {
namespace: '',
filter: '',
sort: defaultSortInfo(this),
};
- setNamespace(namespace) {
+ setNamespace(namespace: string) {
this.setState({namespace});
- this.setState({items: null});
+ this.setState({items: undefined});
this.registerApi({
items: api.pod.list(namespace, items => this.setState({items})),