mirror of
https://github.com/skooner-k8s/skooner.git
synced 2026-08-24 04:16:18 +00:00
Converting apiProxy.js, api.js, and namespace.js to TS
This commit is contained in:
Generated
+901
-901
File diff suppressed because it is too large
Load Diff
@@ -2,8 +2,8 @@ import React from 'react';
|
||||
import Base from './base';
|
||||
|
||||
type Props = {
|
||||
percent: number;
|
||||
percent2: number;
|
||||
percent?: number;
|
||||
percent2?: number;
|
||||
}
|
||||
|
||||
type State = {
|
||||
@@ -76,4 +76,4 @@ function getNextStep(target: number, current: number) {
|
||||
const absDiff = Math.abs(diff);
|
||||
const change = Math.min(absDiff, 0.02);
|
||||
return diff > 0 ? current - change : current + change;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import './field.scss';
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
|
||||
type FieldProps = {
|
||||
name: string;
|
||||
value?: string | null;
|
||||
children?: React.ReactNode[] | null | string;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
const Field = ({name, value, children}: FieldProps) => (
|
||||
|
||||
@@ -5,7 +5,7 @@ import {isAValidURL} from '../utils/string';
|
||||
import Loading from './loading';
|
||||
import Sorter, {sortByDate} from './sorter';
|
||||
import ResourceSvg from '../art/resourceSvg';
|
||||
import {TODO} from "../utils/types";
|
||||
import {TODO} from '../utils/types';
|
||||
|
||||
export function objectMap(items: {[key: string]: string} = {}) {
|
||||
return Object.entries(items).map(([key, value]) => {
|
||||
@@ -126,5 +126,5 @@ function NoResults({items, filter, colSpan}: {items: TODO, filter: TODO, colSpan
|
||||
|
||||
return (
|
||||
<tr />
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import Select, {ValueType} from 'react-select';
|
||||
import Base from './base';
|
||||
import api from '../services/api';
|
||||
import {TODO} from "../utils/types";
|
||||
import {TODO} from '../utils/types';
|
||||
|
||||
interface NamespaceFilterProps {
|
||||
onChange?: Function;
|
||||
|
||||
@@ -3,7 +3,7 @@ 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 {TODO} from '../utils/types';
|
||||
|
||||
export default function NodeCpuChart({items, metrics}: {items: TODO[], metrics: TODO[]}) {
|
||||
const totals = getNodeCpuTotals(items, metrics);
|
||||
|
||||
@@ -3,7 +3,7 @@ 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 {TODO} from '../utils/types';
|
||||
|
||||
export default function NodeRamChart({items, metrics}: {items: TODO[], metrics: TODO[]}) {
|
||||
const totals = getNodeRamTotals(items, metrics);
|
||||
|
||||
@@ -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 {Pod, Metrics} from '../utils/types';
|
||||
|
||||
export default function PodCpuChart({items, metrics}: {items: TODO[], metrics: TODO[]}) {
|
||||
export default function PodCpuChart({items, metrics}: {items?: Pod[], metrics?: _.Dictionary<Metrics>}) {
|
||||
const totals = getPodCpuTotals(items, metrics);
|
||||
const decimals = totals && totals.used > 10 ? 1 : 2;
|
||||
|
||||
@@ -26,7 +26,7 @@ export default function PodCpuChart({items, metrics}: {items: TODO[], metrics: T
|
||||
);
|
||||
}
|
||||
|
||||
function getPodCpuTotals(pods: TODO[], metrics: TODO[]) {
|
||||
function getPodCpuTotals(pods?: Pod[], metrics?: _.Dictionary<Metrics>) {
|
||||
if (!pods || !metrics) return null;
|
||||
|
||||
const used = _(metrics)
|
||||
@@ -35,8 +35,8 @@ function getPodCpuTotals(pods: TODO[], metrics: TODO[]) {
|
||||
|
||||
const available = _(pods)
|
||||
.flatMap(x => x.spec.containers)
|
||||
.filter(x => x.resources && x.resources.requests)
|
||||
.sumBy(x => parseCpu(x.resources.requests.cpu));
|
||||
.filter(x => !!x.resources && !!x.resources.requests)
|
||||
.sumBy(x => parseCpu(x.resources?.requests?.cpu));
|
||||
|
||||
return {
|
||||
used: used / TO_ONE_CPU,
|
||||
|
||||
@@ -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 {Pod, Metrics} from '../utils/types';
|
||||
|
||||
export default function RamChart({items, metrics}: {items: TODO[], metrics: TODO[]}) {
|
||||
export default function RamChart({items, metrics}: {items?: Pod[], metrics?: _.Dictionary<Metrics>}) {
|
||||
const totals = getPodRamTotals(items, metrics);
|
||||
const decimals = totals && totals.used > 10 ? 1 : 2;
|
||||
|
||||
@@ -28,7 +28,7 @@ export default function RamChart({items, metrics}: {items: TODO[], metrics: TODO
|
||||
);
|
||||
}
|
||||
|
||||
export function getPodRamTotals(items:TODO[], metrics:TODO[]) {
|
||||
export function getPodRamTotals(items?: Pod[], metrics?: _.Dictionary<Metrics>) {
|
||||
if (!items || !metrics) return null;
|
||||
|
||||
const metricsContainers = Object.values(metrics).flatMap(x => x.containers);
|
||||
@@ -37,7 +37,7 @@ export function getPodRamTotals(items:TODO[], metrics:TODO[]) {
|
||||
.filter(x => x.resources && x.resources.requests);
|
||||
|
||||
const used = _.sumBy(metricsContainers, x => parseRam(x.usage.memory)) / TO_GB;
|
||||
const available = _.sumBy(podContainers, x => parseRam(x.resources.requests.memory)) / TO_GB;
|
||||
const available = _.sumBy(podContainers, x => parseRam(x.resources?.requests?.memory)) / TO_GB;
|
||||
|
||||
return {used, available};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import Switch from 'react-switch';
|
||||
import Base from './base';
|
||||
import Sorter from './sorter';
|
||||
import {MetadataHeaders, MetadataColumns, TableBody} from './listViewHelpers';
|
||||
import {TODO} from "../utils/types";
|
||||
import {TODO} from '../utils/types';
|
||||
|
||||
interface ReplicaSetsPanelProps {
|
||||
items: TODO[];
|
||||
|
||||
@@ -62,7 +62,7 @@ export default class ScaleButton extends Base<ScaleButtonProps, ScaleButtonState
|
||||
|
||||
async scale() {
|
||||
const {scaleApi} = this.props;
|
||||
const {value = null, scaleInfo = null } = this.state || {};
|
||||
const {value = null, scaleInfo = null} = this.state || {};
|
||||
if (value == null) return;
|
||||
if (scaleInfo == null) return;
|
||||
|
||||
|
||||
@@ -3,7 +3,13 @@ import React, {Component} from 'react';
|
||||
import Base from './base';
|
||||
import ArrowUpSvg from '../art/arrowUpSvg';
|
||||
import ArrowDownSvg from '../art/arrowDownSvg';
|
||||
import {TODO} from "../utils/types";
|
||||
import {TODO} from '../utils/types';
|
||||
|
||||
export interface SortInfo {
|
||||
field: string,
|
||||
direction: string,
|
||||
onSort: (sort: SorterStates) => void,
|
||||
}
|
||||
|
||||
interface SorterProps {
|
||||
sort: {field: string, direction: string, onSort: Function};
|
||||
@@ -14,7 +20,9 @@ interface SorterStates {
|
||||
showEditor: boolean;
|
||||
}
|
||||
|
||||
export function defaultSortInfo(target: Component, field = 'metadata.name', direction = 'asc') {
|
||||
type SortCallback = (item: TODO) => void;
|
||||
|
||||
export function defaultSortInfo(target: Component | SortCallback, field = 'metadata.name', direction = 'asc'): SortInfo {
|
||||
return {
|
||||
field,
|
||||
direction,
|
||||
@@ -22,6 +30,7 @@ export function defaultSortInfo(target: Component, field = 'metadata.name', dire
|
||||
};
|
||||
|
||||
function defaultOnSort(sort: SorterStates) {
|
||||
// @ts-ignore
|
||||
target.setState({sort});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,13 @@ import _ from 'lodash';
|
||||
import {Base64} from 'js-base64';
|
||||
import {request, post, stream, apiFactory, apiFactoryWithNamespace} from './apiProxy';
|
||||
import log from '../utils/log';
|
||||
import { K8sEvent, Namespace, TODO, Metrics } from '../utils/types';
|
||||
|
||||
type DataCallback<T> = (data: T) => void;
|
||||
|
||||
const configMap = apiFactoryWithNamespace('', 'v1', 'configmaps');
|
||||
const event = apiFactoryWithNamespace('', 'v1', 'events');
|
||||
const namespaceService = apiFactory('', 'v1', 'namespaces');
|
||||
const event = apiFactoryWithNamespace<K8sEvent>('', 'v1', 'events');
|
||||
const namespaceService = apiFactory<Namespace>('', 'v1', 'namespaces');
|
||||
const node = apiFactory('', 'v1', 'nodes');
|
||||
const persistentVolume = apiFactory('', 'v1', 'persistentvolumes');
|
||||
const persistentVolumeClaim = apiFactoryWithNamespace('', 'v1', 'persistentvolumeclaims');
|
||||
@@ -70,12 +73,14 @@ async function testAuth() {
|
||||
await post('/apis/authorization.k8s.io/v1/selfsubjectrulesreviews', {spec}, false);
|
||||
}
|
||||
|
||||
function getRules(namespace) {
|
||||
function getRules(namespace: string) {
|
||||
return post('/apis/authorization.k8s.io/v1/selfsubjectrulesreviews', {spec: {namespace}});
|
||||
}
|
||||
|
||||
async function apply(body) {
|
||||
async function apply(body: TODO): Promise<TODO> {
|
||||
const serviceName = _.camelCase(body.kind);
|
||||
|
||||
// @ts-ignore
|
||||
const service = apis[serviceName];
|
||||
if (!service) {
|
||||
throw new Error(`No known service for kind: ${body.kind}`);
|
||||
@@ -85,23 +90,23 @@ async function apply(body) {
|
||||
return await service.post(body);
|
||||
} catch (err) {
|
||||
// Check to see if failed because the record already exists.
|
||||
// If the failure isn't a 409 (i.e. Confilct), just rethrow.
|
||||
// If the failure isn't a 409 (i.e. Conflict), just rethrow.
|
||||
if (err.status !== 409) throw err;
|
||||
|
||||
// We had a confilct. Try a PUT
|
||||
// We had a conflict. Try a PUT
|
||||
return service.put(body);
|
||||
}
|
||||
}
|
||||
|
||||
function metricsFactory() {
|
||||
return {
|
||||
nodes: cb => metrics('/apis/metrics.k8s.io/v1beta1/nodes', cb),
|
||||
node: (name, cb) => metrics(`/apis/metrics.k8s.io/v1beta1/nodes/${name}`, cb),
|
||||
pods: (namespace, cb) => metrics(url(namespace), cb),
|
||||
pod: (namespace, name, cb) => metrics(`/apis/metrics.k8s.io/v1beta1/namespaces/${namespace}/pods/${name}`, cb),
|
||||
nodes: (cb: DataCallback<Metrics[]>) => metrics('/apis/metrics.k8s.io/v1beta1/nodes', cb),
|
||||
node: (name: string, cb: DataCallback<Metrics[]>) => metrics(`/apis/metrics.k8s.io/v1beta1/nodes/${name}`, cb),
|
||||
pods: (namespace: string, cb: DataCallback<Metrics[]>) => metrics(url(namespace), cb),
|
||||
pod: (namespace: string, name: string, cb: DataCallback<Metrics[]>) => metrics(`/apis/metrics.k8s.io/v1beta1/namespaces/${namespace}/pods/${name}`, cb),
|
||||
};
|
||||
|
||||
function url(namespace) {
|
||||
function url(namespace: string) {
|
||||
return namespace ? `/apis/metrics.k8s.io/v1beta1/namespaces/${namespace}/pods` : '/apis/metrics.k8s.io/v1beta1/pods';
|
||||
}
|
||||
}
|
||||
@@ -109,11 +114,11 @@ function metricsFactory() {
|
||||
function oidcFactory() {
|
||||
return {
|
||||
get: () => request('/oidc'),
|
||||
post: (code, redirectUri) => post('/oidc', {code, redirectUri}),
|
||||
post: (code: string, redirectUri: string) => post('/oidc', {code, redirectUri}),
|
||||
};
|
||||
}
|
||||
|
||||
function metrics(url, cb) {
|
||||
function metrics(url: string, cb: DataCallback<Metrics[]>) {
|
||||
const handel = setInterval(getMetrics, 10000);
|
||||
getMetrics();
|
||||
|
||||
@@ -137,14 +142,14 @@ function swagger() {
|
||||
return request('/openapi/v2');
|
||||
}
|
||||
|
||||
function exec(namespace, name, container, cb) {
|
||||
function exec(namespace: string, name: string, container: string, cb: DataCallback<string[]>) {
|
||||
const url = `/api/v1/namespaces/${namespace}/pods/${name}/exec?container=${container}&command=sh&stdin=1&stderr=1&stdout=1&tty=1`;
|
||||
const additionalProtocols = ['v4.channel.k8s.io', 'v3.channel.k8s.io', 'v2.channel.k8s.io', 'channel.k8s.io'];
|
||||
return stream(url, cb, {additionalProtocols, isJson: false});
|
||||
}
|
||||
|
||||
function logs(namespace, name, container, tailLines, showPrevious, cb) {
|
||||
const items = [];
|
||||
function logs(namespace: string, name: string, container: string, tailLines: number, showPrevious: boolean, cb: DataCallback<string[]>) {
|
||||
const items: string[] = [];
|
||||
const url = `/api/v1/namespaces/${namespace}/pods/${name}/log?container=${container}&previous=${showPrevious}&tailLines=${tailLines}&follow=true`;
|
||||
const {cancel} = stream(url, transformer, {isJson: false, connectCb});
|
||||
return cancel;
|
||||
@@ -153,7 +158,7 @@ function logs(namespace, name, container, tailLines, showPrevious, cb) {
|
||||
items.length = 0;
|
||||
}
|
||||
|
||||
function transformer(item) {
|
||||
function transformer(item: string) {
|
||||
if (!item) return; // For some reason, this api returns a lot of empty strings
|
||||
|
||||
const message = Base64.decode(item);
|
||||
@@ -1,5 +1,21 @@
|
||||
import {getToken, logout} from './auth';
|
||||
import log from '../utils/log';
|
||||
import {ApiItem} from '../utils/types';
|
||||
|
||||
type StreamCallback<T> = (data: T) => void;
|
||||
type ErrorCallback = (err: Error) => void;
|
||||
type FailCallback = () => void;
|
||||
|
||||
type StreamSocket = {
|
||||
cancel: () => void;
|
||||
getSocket: () => WebSocket;
|
||||
};
|
||||
|
||||
type StreamArgs = {
|
||||
isJson: boolean;
|
||||
additionalProtocols?: string[];
|
||||
connectCb?: () => void;
|
||||
}
|
||||
|
||||
const {host, href, hash, search} = window.location;
|
||||
const nonHashedUrl = href.replace(hash, '').replace(search, '');
|
||||
@@ -8,7 +24,7 @@ const BASE_HTTP_URL = isDev && host === 'localhost:4653' ? 'http://localhost:465
|
||||
const BASE_WS_URL = BASE_HTTP_URL.replace('http', 'ws');
|
||||
const JSON_HEADERS = {Accept: 'application/json', 'Content-Type': 'application/json'};
|
||||
|
||||
export async function request(path, params, autoLogoutOnAuthError = true) {
|
||||
export async function request(path: string, params?: any, autoLogoutOnAuthError = true) {
|
||||
const opts = Object.assign({headers: {}}, params);
|
||||
|
||||
const token = getToken();
|
||||
@@ -33,6 +49,7 @@ export async function request(path, params, autoLogoutOnAuthError = true) {
|
||||
}
|
||||
|
||||
const error = new Error(message);
|
||||
// @ts-ignore
|
||||
error.status = status;
|
||||
throw error;
|
||||
}
|
||||
@@ -40,76 +57,71 @@ export async function request(path, params, autoLogoutOnAuthError = true) {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export function apiFactory(group, version, resource) {
|
||||
export function apiFactory<T extends ApiItem<any, any>>(group: string, version: string, resource: string) {
|
||||
const apiRoot = getApiRoot(group, version);
|
||||
const url = `${apiRoot}/${resource}`;
|
||||
return {
|
||||
resource: {group, resource},
|
||||
list: (cb, errCb) => streamResults(url, cb, errCb),
|
||||
get: (name, cb, errCb) => streamResult(url, name, cb, errCb),
|
||||
post: body => post(url, body),
|
||||
put: body => put(`${url}/${body.metadata.name}`, body),
|
||||
delete: name => remove(`${url}/${name}`),
|
||||
list: (cb: StreamCallback<T[]>, errCb?: ErrorCallback) => streamResults(url, cb, errCb),
|
||||
get: (name: string, cb: StreamCallback<T>, errCb?: ErrorCallback) => streamResult(url, name, cb, errCb),
|
||||
post: (body: any) => post(url, body),
|
||||
put: (body: any) => put(`${url}/${body.metadata.name}`, body),
|
||||
delete: (name: string) => remove(`${url}/${name}`),
|
||||
};
|
||||
}
|
||||
|
||||
export function apiFactoryWithNamespace(group, version, resource, includeScale) {
|
||||
export function apiFactoryWithNamespace<T extends ApiItem<any, any>>(group: string, version: string, resource: string, includeScale = false) {
|
||||
const apiRoot = getApiRoot(group, version);
|
||||
const results = {
|
||||
return {
|
||||
resource: {group, resource},
|
||||
list: (namespace, cb, errCb) => streamResults(url(namespace), cb, errCb),
|
||||
get: (namespace, name, cb, errCb) => streamResult(url(namespace), name, cb, errCb),
|
||||
post: body => post(url(body.metadata.namespace), body),
|
||||
put: body => put(`${url(body.metadata.namespace)}/${body.metadata.name}`, body),
|
||||
delete: (namespace, name) => remove(`${url(namespace)}/${name}`),
|
||||
list: (namespace: string, cb: StreamCallback<T[]>, errCb?: ErrorCallback) => streamResults(url(namespace), cb, errCb),
|
||||
get: (namespace: string, name: string, cb: StreamCallback<T>, 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),
|
||||
delete: (namespace: string, name: string) => remove(`${url(namespace)}/${name}`),
|
||||
scale: includeScale ? apiScaleFactory(apiRoot, resource) : undefined,
|
||||
};
|
||||
|
||||
if (includeScale) {
|
||||
results.scale = apiScaleFactory(apiRoot, resource);
|
||||
}
|
||||
|
||||
return results;
|
||||
|
||||
function url(namespace) {
|
||||
function url(namespace: string) {
|
||||
return namespace ? `${apiRoot}/namespaces/${namespace}/${resource}` : `${apiRoot}/${resource}`;
|
||||
}
|
||||
}
|
||||
|
||||
function getApiRoot(group, version) {
|
||||
function getApiRoot(group: string, version: string) {
|
||||
return group ? `/apis/${group}/${version}` : `api/${version}`;
|
||||
}
|
||||
|
||||
function apiScaleFactory(apiRoot, resource) {
|
||||
function apiScaleFactory(apiRoot: string, resource: string) {
|
||||
return {
|
||||
get: (namespace, name) => request(url(namespace, name)),
|
||||
put: body => put(url(body.metadata.namespace, body.metadata.name), body),
|
||||
get: (namespace: string, name: string) => request(url(namespace, name)),
|
||||
put: (body: any) => put(url(body.metadata.namespace, body.metadata.name), body),
|
||||
};
|
||||
|
||||
function url(namespace, name) {
|
||||
function url(namespace: string, name: string) {
|
||||
return `${apiRoot}/namespaces/${namespace}/${resource}/${name}/scale`;
|
||||
}
|
||||
}
|
||||
|
||||
export function post(url, json, autoLogoutOnAuthError = true) {
|
||||
export function post(url: string, json: any, autoLogoutOnAuthError = true) {
|
||||
const body = JSON.stringify(json);
|
||||
const opts = {method: 'POST', body, headers: JSON_HEADERS};
|
||||
return request(url, opts, autoLogoutOnAuthError);
|
||||
}
|
||||
|
||||
export function put(url, json, autoLogoutOnAuthError = true) {
|
||||
export function put(url: string, json: any, autoLogoutOnAuthError = true) {
|
||||
const body = JSON.stringify(json);
|
||||
const opts = {method: 'PUT', body, headers: JSON_HEADERS};
|
||||
return request(url, opts, autoLogoutOnAuthError);
|
||||
}
|
||||
|
||||
export function remove(url) {
|
||||
export function remove(url: string) {
|
||||
const opts = {method: 'DELETE', headers: JSON_HEADERS};
|
||||
return request(url, opts);
|
||||
}
|
||||
|
||||
export async function streamResult(url, name, cb, errCb) {
|
||||
export async function streamResult<T>(url: string, name: string, cb: StreamCallback<T>, errCb?: ErrorCallback) {
|
||||
let isCancelled = false;
|
||||
let socket;
|
||||
let socket: StreamSocket;
|
||||
run();
|
||||
|
||||
return cancel;
|
||||
@@ -124,7 +136,9 @@ export async function streamResult(url, name, cb, errCb) {
|
||||
const fieldSelector = encodeURIComponent(`metadata.name=${name}`);
|
||||
const watchUrl = `${url}?watch=1&fieldSelector=${fieldSelector}`;
|
||||
|
||||
socket = stream(watchUrl, x => cb(x.object), {isJson: true});
|
||||
// TODO: fix me
|
||||
// @ts-ignore
|
||||
socket = stream<T>(watchUrl, x => cb(x.object), {isJson: true});
|
||||
} catch (err) {
|
||||
log.error('Error in api request', {err, url});
|
||||
if (errCb) errCb(err);
|
||||
@@ -139,10 +153,10 @@ export async function streamResult(url, name, cb, errCb) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function streamResults(url, cb, errCb) {
|
||||
const results = {};
|
||||
export async function streamResults<T extends ApiItem<any, any>>(url: string, cb: StreamCallback<T[]>, errCb?: ErrorCallback) {
|
||||
const results: {[id: string]: T} = {};
|
||||
let isCancelled = false;
|
||||
let socket;
|
||||
let socket: StreamSocket;
|
||||
run();
|
||||
|
||||
return cancel;
|
||||
@@ -169,7 +183,7 @@ export async function streamResults(url, cb, errCb) {
|
||||
if (socket) socket.cancel();
|
||||
}
|
||||
|
||||
function add(items, kind) {
|
||||
function add(items: T[], kind: string) {
|
||||
const fixedKind = kind.slice(0, -4); // Trim off the word "List" from the end of the string
|
||||
for (const item of items) {
|
||||
item.kind = fixedKind;
|
||||
@@ -179,7 +193,8 @@ export async function streamResults(url, cb, errCb) {
|
||||
push();
|
||||
}
|
||||
|
||||
function update({type, object}) {
|
||||
function update({type, object}: {type: string, object: T}) {
|
||||
// @ts-ignore
|
||||
object.actionType = type; // eslint-disable-line no-param-reassign
|
||||
|
||||
switch (type) {
|
||||
@@ -208,7 +223,7 @@ export async function streamResults(url, cb, errCb) {
|
||||
log.error('Error in update', {type, object});
|
||||
break;
|
||||
default:
|
||||
log.error('Unknown update type', type);
|
||||
log.error('Unknown update type', {type});
|
||||
}
|
||||
|
||||
push();
|
||||
@@ -220,9 +235,12 @@ export async function streamResults(url, cb, errCb) {
|
||||
}
|
||||
}
|
||||
|
||||
export function stream(url, cb, args) {
|
||||
let connection;
|
||||
let isCancelled;
|
||||
export function stream<T>(url: string, cb: StreamCallback<T>, args: StreamArgs) {
|
||||
let connection: {
|
||||
close: () => void;
|
||||
socket: WebSocket;
|
||||
};
|
||||
let isCancelled: boolean;
|
||||
const {isJson, additionalProtocols, connectCb} = args;
|
||||
|
||||
connect();
|
||||
@@ -240,7 +258,7 @@ export function stream(url, cb, args) {
|
||||
|
||||
function connect() {
|
||||
if (connectCb) connectCb();
|
||||
connection = connectStream(url, cb, onFail, isJson, additionalProtocols);
|
||||
connection = connectStream<T>(url, cb, onFail, isJson, additionalProtocols);
|
||||
}
|
||||
|
||||
function onFail() {
|
||||
@@ -251,7 +269,7 @@ export function stream(url, cb, args) {
|
||||
}
|
||||
}
|
||||
|
||||
function connectStream(path, cb, onFail, isJson, additionalProtocols = []) {
|
||||
function connectStream<T>(path: string, cb: StreamCallback<T>, onFail: FailCallback, isJson: boolean, additionalProtocols: string[] = []) {
|
||||
let isClosing = false;
|
||||
|
||||
const token = getToken();
|
||||
@@ -277,14 +295,14 @@ function connectStream(path, cb, onFail, isJson, additionalProtocols = []) {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
function onMessage(body) {
|
||||
function onMessage(body: any) {
|
||||
if (isClosing) return;
|
||||
|
||||
const item = isJson ? JSON.parse(body.data) : body.data;
|
||||
cb(item);
|
||||
}
|
||||
|
||||
function onClose(...args) {
|
||||
function onClose(...args: any) {
|
||||
if (isClosing) return;
|
||||
isClosing = true;
|
||||
|
||||
@@ -296,12 +314,12 @@ function connectStream(path, cb, onFail, isJson, additionalProtocols = []) {
|
||||
onFail();
|
||||
}
|
||||
|
||||
function onError(err) {
|
||||
function onError(err: any) {
|
||||
log.error('Error in api stream', {err, path});
|
||||
}
|
||||
}
|
||||
|
||||
function combinePath(base, path) {
|
||||
function combinePath(base: string, path: string) {
|
||||
if (base.endsWith('/')) base = base.slice(0, -1); // eslint-disable-line no-param-reassign
|
||||
if (path.startsWith('/')) path = path.slice(1); // eslint-disable-line no-param-reassign
|
||||
return `${base}/${path}`;
|
||||
@@ -1,4 +1,4 @@
|
||||
import {TODO} from "./types";
|
||||
import {TODO} from './types';
|
||||
|
||||
export default function test(filter = '', ...values: string[]) {
|
||||
const value = filter.toLowerCase();
|
||||
@@ -20,7 +20,7 @@ export function filterByOwner(items: TODO[], owner: TODO) {
|
||||
});
|
||||
}
|
||||
|
||||
export function filterByOwners(items: TODO[] , owners: TODO) {
|
||||
export function filterByOwners(items: TODO[], owners: TODO) {
|
||||
if (!items || !owners) return null;
|
||||
|
||||
const uids = owners.map((x: any) => x.metadata.uid);
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import _ from 'lodash';
|
||||
import {parseRam, parseCpu} from './unitHelpers';
|
||||
import {TODO} from "./types";
|
||||
import {TODO, Pod, Node, Metrics} from './types';
|
||||
|
||||
export default function getMetrics(items: TODO[], metrics: TODO) {
|
||||
if (!items || !metrics) return null;
|
||||
export default function getMetrics(items?: Pod[], metrics?: Metrics[]) {
|
||||
if (!items || !metrics) return undefined;
|
||||
|
||||
const names = _.map(items, x => x.metadata.name);
|
||||
const filteredMetrics = metrics.filter((x: TODO) => names.includes(x.metadata.name));
|
||||
const filteredMetrics = metrics.filter(x => names.includes(x.metadata.name));
|
||||
|
||||
return _.keyBy(filteredMetrics, 'metadata.name');
|
||||
}
|
||||
|
||||
|
||||
// Node helpers
|
||||
export function getNodeResourceValue(node: TODO, pods: TODO, resource: string, type: string, phases: string[]) {
|
||||
export function getNodeResourceValue(node: Node | undefined, pods: Pod[] | undefined, resource: string, type: string, phases: string[]) {
|
||||
if (!node || !pods) return null;
|
||||
|
||||
return _(pods)
|
||||
@@ -25,13 +25,13 @@ export function getNodeResourceValue(node: TODO, pods: TODO, resource: string, t
|
||||
export function getNodeResourcePercent(node: TODO, pods: TODO, resource: string, type: string) {
|
||||
const used = getNodeResourceValue(node, pods, resource, type, ['Running']);
|
||||
const available = getNodeResourcesAvailable(node, resource);
|
||||
return used && available ? used / available: null;
|
||||
return used && available ? used / available : null;
|
||||
}
|
||||
|
||||
export function getNodeUsagePercent(node: TODO, metrics: TODO, resource: string) {
|
||||
const used = getNodeUsage(node, metrics, resource);
|
||||
const available = getNodeResourcesAvailable(node, resource);
|
||||
return used && available ? used / available: null;
|
||||
return used && available ? used / available : null;
|
||||
}
|
||||
|
||||
export function getNodeResourcesAvailable(node: TODO, resource: string) {
|
||||
@@ -50,7 +50,7 @@ export function getNodeUsage(node: TODO, metrics: TODO, resource: string) {
|
||||
export function getPodResourcePercent(item: TODO, metrics: TODO, resource: string, type: string) {
|
||||
const actual = getPodUsage(item, metrics, resource);
|
||||
const request = getPodResourceValue(item, resource, type);
|
||||
return actual ? actual / request: null;
|
||||
return actual ? actual / request : null;
|
||||
}
|
||||
|
||||
export function getPodUsage(pod: TODO, metrics: TODO, resource: string) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {TODO} from "./types";
|
||||
import {TODO} from './types';
|
||||
|
||||
/**
|
||||
* @param {*status* object with a status field (most likely the row from the TableBody)}
|
||||
|
||||
@@ -1 +1,57 @@
|
||||
export type TODO = any;
|
||||
export type TODO = any;
|
||||
|
||||
export type ApiItem<TSpec, TStatus> = {
|
||||
kind: string;
|
||||
metadata: Metadata;
|
||||
spec: TSpec;
|
||||
status: TStatus
|
||||
}
|
||||
|
||||
interface Metadata {
|
||||
uid: string;
|
||||
resourceVersion: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface Container {
|
||||
resources?: {
|
||||
requests?: {
|
||||
cpu?: string;
|
||||
memory?: string;
|
||||
}
|
||||
}
|
||||
usage: {
|
||||
cpu?: string;
|
||||
memory?: string;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Metrics extends ApiItem<undefined, undefined> {
|
||||
containers: Container[];
|
||||
}
|
||||
|
||||
interface NamespaceStatus {
|
||||
phase: string;
|
||||
}
|
||||
|
||||
export interface Namespace extends ApiItem<undefined, NamespaceStatus> {
|
||||
}
|
||||
|
||||
export interface Node extends ApiItem<undefined, undefined> {
|
||||
|
||||
}
|
||||
|
||||
export interface K8sEvent extends ApiItem<undefined, undefined>{
|
||||
}
|
||||
|
||||
interface PodSpec {
|
||||
nodeName: string;
|
||||
containers: Container[];
|
||||
}
|
||||
|
||||
interface PodStatus {
|
||||
phase: string;
|
||||
}
|
||||
|
||||
export interface Pod extends ApiItem<PodSpec, PodStatus>{
|
||||
}
|
||||
@@ -7,15 +7,15 @@ export const TO_GB = 1024 * 1024 * 1024;
|
||||
export const TO_ONE_M_CPU = 1000000;
|
||||
export const TO_ONE_CPU = 1000000000;
|
||||
|
||||
export function parseDiskSpace(value: string) {
|
||||
export function parseDiskSpace(value?: string) {
|
||||
return parseUnitsOfBytes(value);
|
||||
}
|
||||
|
||||
export function parseRam(value: string) {
|
||||
export function parseRam(value?: string) {
|
||||
return parseUnitsOfBytes(value);
|
||||
}
|
||||
|
||||
function parseUnitsOfBytes(value: string) {
|
||||
function parseUnitsOfBytes(value?: string) {
|
||||
if (!value) return 0;
|
||||
|
||||
const groups = value.match(/(\d+)([BKMGTPEe])?(i)?(\d+)?/)!;
|
||||
@@ -55,7 +55,7 @@ export function unparseRam(value: number) {
|
||||
};
|
||||
}
|
||||
|
||||
export function parseCpu(value: string) {
|
||||
export function parseCpu(value?: string) {
|
||||
if (!value) return 0;
|
||||
|
||||
const number = parseInt(value, 10);
|
||||
|
||||
@@ -8,17 +8,30 @@ import MetadataFields from '../components/metadataFields';
|
||||
import DeleteButton from '../components/deleteButton';
|
||||
import PodsPanel from '../components/podsPanel';
|
||||
import EventsPanel from '../components/eventsPanel';
|
||||
import {defaultSortInfo} from '../components/sorter';
|
||||
import {defaultSortInfo, SortInfo} from '../components/sorter';
|
||||
import ChartsContainer from '../components/chartsContainer';
|
||||
import PodStatusChart from '../components/podStatusChart';
|
||||
import PodCpuChart from '../components/podCpuChart';
|
||||
import PodRamChart from '../components/podRamChart';
|
||||
import getMetrics from '../utils/metricsHelpers';
|
||||
import { Namespace, K8sEvent, Pod, Metrics } from '../utils/types';
|
||||
|
||||
type Props = {
|
||||
namespace: string;
|
||||
}
|
||||
|
||||
type State = {
|
||||
podsSort: SortInfo;
|
||||
item?: Namespace;
|
||||
events?: K8sEvent[];
|
||||
pods?: Pod[];
|
||||
podMetrics?: Metrics[];
|
||||
}
|
||||
|
||||
const service = api.namespace;
|
||||
|
||||
export default class Namespace extends Base {
|
||||
state = {
|
||||
export default class NamespaceView extends Base<Props, State> {
|
||||
state:State = {
|
||||
podsSort: defaultSortInfo(x => this.setState({podsSort: x})),
|
||||
};
|
||||
|
||||
@@ -73,6 +86,9 @@ export default class Namespace extends Base {
|
||||
/>
|
||||
|
||||
<div className='contentPanel_header'>Events</div>
|
||||
|
||||
{/*
|
||||
// @ts-ignore */}
|
||||
<EventsPanel items={events} />
|
||||
</div>
|
||||
);
|
||||
Generated
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
Reference in New Issue
Block a user