@backstage/plugin-kubernetes 0.4.17 → 0.4.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/index.esm.js +643 -637
- package/dist/index.esm.js.map +1 -1
- package/package.json +12 -12
package/dist/index.esm.js
CHANGED
|
@@ -3,14 +3,15 @@ import * as React from 'react';
|
|
|
3
3
|
import React__default, { Fragment, useState, useEffect, useContext } from 'react';
|
|
4
4
|
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
5
5
|
import { Routes, Route } from 'react-router-dom';
|
|
6
|
-
import { Typography, Chip, makeStyles, createStyles, Button, Drawer,
|
|
7
|
-
import { WarningPanel, SubvalueCell, StatusError, StatusOK, StatusAborted, Button as Button$1, CodeSnippet, StructuredMetadataTable,
|
|
6
|
+
import { Typography, Chip, Grid, makeStyles, createStyles, Button, Drawer, IconButton, FormControlLabel, Switch, Accordion, AccordionSummary, AccordionDetails, Divider, Stepper, Step, StepLabel } from '@material-ui/core';
|
|
7
|
+
import { WarningPanel, InfoCard, Table, SubvalueCell, StatusError, StatusOK, StatusAborted, Button as Button$1, CodeSnippet, StructuredMetadataTable, Page, Content, Progress, MissingAnnotationEmptyState } from '@backstage/core-components';
|
|
8
|
+
import EmptyStateImage from './assets/emptystate.svg';
|
|
8
9
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
9
10
|
import Close from '@material-ui/icons/Close';
|
|
10
11
|
import OpenInNewIcon from '@material-ui/icons/OpenInNew';
|
|
11
12
|
import { withStyles } from '@material-ui/core/styles';
|
|
12
13
|
import jsYaml from 'js-yaml';
|
|
13
|
-
import
|
|
14
|
+
import { useInterval } from 'react-use';
|
|
14
15
|
import lodash from 'lodash';
|
|
15
16
|
import PauseIcon from '@material-ui/icons/Pause';
|
|
16
17
|
import ErrorOutlineIcon from '@material-ui/icons/ErrorOutline';
|
|
@@ -172,6 +173,123 @@ const ErrorPanel$1 = ({
|
|
|
172
173
|
variant: "body2"
|
|
173
174
|
}, "Errors: ", errorMessage));
|
|
174
175
|
|
|
176
|
+
const columns$1 = [
|
|
177
|
+
{
|
|
178
|
+
title: "cluster",
|
|
179
|
+
width: "15%",
|
|
180
|
+
render: (detectedError) => detectedError.cluster
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
title: "kind",
|
|
184
|
+
width: "15%",
|
|
185
|
+
render: (detectedError) => detectedError.kind
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
title: "name",
|
|
189
|
+
width: "30%",
|
|
190
|
+
render: (detectedError) => {
|
|
191
|
+
const errorCount = detectedError.names.length;
|
|
192
|
+
if (errorCount === 0) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const displayName = detectedError.names[0];
|
|
196
|
+
const otherErrorCount = errorCount - 1;
|
|
197
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, displayName, " ", otherErrorCount > 0 && /* @__PURE__ */ React.createElement(Chip, {
|
|
198
|
+
label: `+ ${otherErrorCount} other${otherErrorCount > 1 ? "s" : ""}`,
|
|
199
|
+
size: "small"
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
title: "messages",
|
|
205
|
+
width: "40%",
|
|
206
|
+
render: (detectedError) => /* @__PURE__ */ React.createElement(React.Fragment, null, detectedError.message.map((m, i) => /* @__PURE__ */ React.createElement("div", {
|
|
207
|
+
key: i
|
|
208
|
+
}, m)))
|
|
209
|
+
}
|
|
210
|
+
];
|
|
211
|
+
const sortBySeverity = (a, b) => {
|
|
212
|
+
if (a.severity < b.severity) {
|
|
213
|
+
return 1;
|
|
214
|
+
} else if (b.severity < a.severity) {
|
|
215
|
+
return -1;
|
|
216
|
+
}
|
|
217
|
+
return 0;
|
|
218
|
+
};
|
|
219
|
+
const ErrorEmptyState = () => {
|
|
220
|
+
return /* @__PURE__ */ React.createElement(Grid, {
|
|
221
|
+
container: true,
|
|
222
|
+
justifyContent: "space-around",
|
|
223
|
+
direction: "row",
|
|
224
|
+
alignItems: "center",
|
|
225
|
+
spacing: 2
|
|
226
|
+
}, /* @__PURE__ */ React.createElement(Grid, {
|
|
227
|
+
item: true,
|
|
228
|
+
xs: 4
|
|
229
|
+
}, /* @__PURE__ */ React.createElement(Typography, {
|
|
230
|
+
variant: "h5"
|
|
231
|
+
}, "Nice! There are no errors to report!")), /* @__PURE__ */ React.createElement(Grid, {
|
|
232
|
+
item: true,
|
|
233
|
+
xs: 4
|
|
234
|
+
}, /* @__PURE__ */ React.createElement("img", {
|
|
235
|
+
src: EmptyStateImage,
|
|
236
|
+
alt: "EmptyState",
|
|
237
|
+
"data-testid": "emptyStateImg"
|
|
238
|
+
})));
|
|
239
|
+
};
|
|
240
|
+
const ErrorReporting = ({detectedErrors}) => {
|
|
241
|
+
const errors = Array.from(detectedErrors.values()).flat().sort(sortBySeverity);
|
|
242
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, errors.length === 0 ? /* @__PURE__ */ React.createElement(InfoCard, {
|
|
243
|
+
title: "Error Reporting"
|
|
244
|
+
}, /* @__PURE__ */ React.createElement(ErrorEmptyState, null)) : /* @__PURE__ */ React.createElement(Table, {
|
|
245
|
+
title: "Error Reporting",
|
|
246
|
+
data: errors,
|
|
247
|
+
columns: columns$1,
|
|
248
|
+
options: {paging: true, search: false}
|
|
249
|
+
}));
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const groupResponses = (fetchResponse) => {
|
|
253
|
+
return fetchResponse.reduce((prev, next) => {
|
|
254
|
+
switch (next.type) {
|
|
255
|
+
case "deployments":
|
|
256
|
+
prev.deployments.push(...next.resources);
|
|
257
|
+
break;
|
|
258
|
+
case "pods":
|
|
259
|
+
prev.pods.push(...next.resources);
|
|
260
|
+
break;
|
|
261
|
+
case "replicasets":
|
|
262
|
+
prev.replicaSets.push(...next.resources);
|
|
263
|
+
break;
|
|
264
|
+
case "services":
|
|
265
|
+
prev.services.push(...next.resources);
|
|
266
|
+
break;
|
|
267
|
+
case "configmaps":
|
|
268
|
+
prev.configMaps.push(...next.resources);
|
|
269
|
+
break;
|
|
270
|
+
case "horizontalpodautoscalers":
|
|
271
|
+
prev.horizontalPodAutoscalers.push(...next.resources);
|
|
272
|
+
break;
|
|
273
|
+
case "ingresses":
|
|
274
|
+
prev.ingresses.push(...next.resources);
|
|
275
|
+
break;
|
|
276
|
+
case "customresources":
|
|
277
|
+
prev.customResources.push(...next.resources);
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
return prev;
|
|
281
|
+
}, {
|
|
282
|
+
pods: [],
|
|
283
|
+
replicaSets: [],
|
|
284
|
+
deployments: [],
|
|
285
|
+
services: [],
|
|
286
|
+
configMaps: [],
|
|
287
|
+
horizontalPodAutoscalers: [],
|
|
288
|
+
ingresses: [],
|
|
289
|
+
customResources: []
|
|
290
|
+
});
|
|
291
|
+
};
|
|
292
|
+
|
|
175
293
|
const imageChips = (pod) => {
|
|
176
294
|
var _a, _b;
|
|
177
295
|
const containerStatuses2 = (_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : [];
|
|
@@ -243,141 +361,307 @@ const renderCondition = (condition) => {
|
|
|
243
361
|
return [condition.type, /* @__PURE__ */ React__default.createElement(StatusAborted, null)];
|
|
244
362
|
};
|
|
245
363
|
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
try {
|
|
268
|
-
requestBody = await kubernetesAuthProvidersApi.decorateRequestBodyForAuth(authProviderStr, requestBody);
|
|
269
|
-
} catch (e) {
|
|
270
|
-
setError(e.message);
|
|
271
|
-
return;
|
|
364
|
+
const detectErrorsInObjects = (objects, kind, clusterName, errorMappers) => {
|
|
365
|
+
var _a, _b;
|
|
366
|
+
const errors = new Map();
|
|
367
|
+
for (const object of objects) {
|
|
368
|
+
for (const errorMapper of errorMappers) {
|
|
369
|
+
if (errorMapper.errorExists(object)) {
|
|
370
|
+
const message = errorMapper.messageAccessor(object);
|
|
371
|
+
const dedupKey = message.join("");
|
|
372
|
+
const value = errors.get(dedupKey);
|
|
373
|
+
const name = (_b = (_a = object.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown";
|
|
374
|
+
if (value !== void 0) {
|
|
375
|
+
value.names.push(name);
|
|
376
|
+
errors.set(dedupKey, value);
|
|
377
|
+
} else {
|
|
378
|
+
errors.set(dedupKey, {
|
|
379
|
+
cluster: clusterName,
|
|
380
|
+
kind,
|
|
381
|
+
names: [name],
|
|
382
|
+
message,
|
|
383
|
+
severity: errorMapper.severity
|
|
384
|
+
});
|
|
272
385
|
}
|
|
273
386
|
}
|
|
274
|
-
|
|
275
|
-
setKubernetesObjects(await kubernetesApi.getObjectsByEntity(requestBody));
|
|
276
|
-
} catch (e) {
|
|
277
|
-
setError(e.message);
|
|
278
|
-
return;
|
|
279
|
-
}
|
|
280
|
-
})();
|
|
281
|
-
}, [entity.metadata.name, kubernetesApi, kubernetesAuthProvidersApi]);
|
|
282
|
-
return {
|
|
283
|
-
kubernetesObjects,
|
|
284
|
-
error
|
|
285
|
-
};
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
const PodNamesWithErrorsContext = React__default.createContext(new Set());
|
|
289
|
-
|
|
290
|
-
const GroupedResponsesContext = React__default.createContext({
|
|
291
|
-
pods: [],
|
|
292
|
-
replicaSets: [],
|
|
293
|
-
deployments: [],
|
|
294
|
-
services: [],
|
|
295
|
-
configMaps: [],
|
|
296
|
-
horizontalPodAutoscalers: [],
|
|
297
|
-
ingresses: [],
|
|
298
|
-
customResources: []
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
const ClusterContext = React__default.createContext({
|
|
302
|
-
name: ""
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
const kindMappings$1 = {
|
|
306
|
-
deployment: "deployment",
|
|
307
|
-
ingress: "ingress",
|
|
308
|
-
service: "service",
|
|
309
|
-
horizontalpodautoscaler: "deployment"
|
|
310
|
-
};
|
|
311
|
-
function standardFormatter(options) {
|
|
312
|
-
var _a, _b;
|
|
313
|
-
const result = new URL(options.dashboardUrl.href);
|
|
314
|
-
const name = (_a = options.object.metadata) == null ? void 0 : _a.name;
|
|
315
|
-
const namespace = (_b = options.object.metadata) == null ? void 0 : _b.namespace;
|
|
316
|
-
const validKind = kindMappings$1[options.kind.toLocaleLowerCase("en-US")];
|
|
317
|
-
if (namespace) {
|
|
318
|
-
result.searchParams.set("namespace", namespace);
|
|
319
|
-
}
|
|
320
|
-
if (validKind && name && namespace) {
|
|
321
|
-
result.hash = `/${validKind}/${namespace}/${name}`;
|
|
322
|
-
} else if (namespace) {
|
|
323
|
-
result.hash = "/workloads";
|
|
324
|
-
}
|
|
325
|
-
return result;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
const kindMappings = {
|
|
329
|
-
deployment: "apps.deployment",
|
|
330
|
-
ingress: "networking.k8s.io.ingress",
|
|
331
|
-
service: "service",
|
|
332
|
-
horizontalpodautoscaler: "autoscaling.horizontalpodautoscaler"
|
|
333
|
-
};
|
|
334
|
-
function rancherFormatter(options) {
|
|
335
|
-
var _a, _b;
|
|
336
|
-
const result = new URL(options.dashboardUrl.href);
|
|
337
|
-
const name = (_a = options.object.metadata) == null ? void 0 : _a.name;
|
|
338
|
-
const namespace = (_b = options.object.metadata) == null ? void 0 : _b.namespace;
|
|
339
|
-
const validKind = kindMappings[options.kind.toLocaleLowerCase("en-US")];
|
|
340
|
-
if (validKind && name && namespace) {
|
|
341
|
-
result.pathname += `explorer/${validKind}/${namespace}/${name}`;
|
|
342
|
-
} else if (namespace) {
|
|
343
|
-
result.pathname += "explorer/workload";
|
|
387
|
+
}
|
|
344
388
|
}
|
|
345
|
-
return
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
function openshiftFormatter(_options) {
|
|
349
|
-
throw new Error("OpenShift formatter is not yet implemented. Please, contribute!");
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
function aksFormatter(_options) {
|
|
353
|
-
throw new Error("AKS formatter is not yet implemented. Please, contribute!");
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function eksFormatter(_options) {
|
|
357
|
-
throw new Error("EKS formatter is not yet implemented. Please, contribute!");
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
function gkeFormatter(_options) {
|
|
361
|
-
throw new Error("GKE formatter is not yet implemented. Please, contribute!");
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const clusterLinksFormatters = {
|
|
365
|
-
standard: standardFormatter,
|
|
366
|
-
rancher: rancherFormatter,
|
|
367
|
-
openshift: openshiftFormatter,
|
|
368
|
-
aks: aksFormatter,
|
|
369
|
-
eks: eksFormatter,
|
|
370
|
-
gke: gkeFormatter
|
|
389
|
+
return Array.from(errors.values());
|
|
371
390
|
};
|
|
372
|
-
const defaultFormatterName = "standard";
|
|
373
391
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
392
|
+
const podErrorMappers = [
|
|
393
|
+
{
|
|
394
|
+
severity: 5,
|
|
395
|
+
errorExplanation: "status-message",
|
|
396
|
+
errorExists: (pod) => {
|
|
397
|
+
var _a;
|
|
398
|
+
return ((_a = pod.status) == null ? void 0 : _a.message) !== void 0;
|
|
399
|
+
},
|
|
400
|
+
messageAccessor: (pod) => {
|
|
401
|
+
var _a, _b;
|
|
402
|
+
return [(_b = (_a = pod.status) == null ? void 0 : _a.message) != null ? _b : ""];
|
|
403
|
+
}
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
severity: 4,
|
|
407
|
+
errorExplanation: "containers-restarting",
|
|
408
|
+
errorExists: (pod) => {
|
|
409
|
+
return totalRestarts(pod) > 3;
|
|
410
|
+
},
|
|
411
|
+
messageAccessor: (pod) => {
|
|
412
|
+
var _a, _b;
|
|
413
|
+
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).filter((cs) => cs.restartCount > 0).map((cs) => `container=${cs.name} restarted ${cs.restartCount} times`);
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
{
|
|
417
|
+
severity: 5,
|
|
418
|
+
errorExplanation: "condition-message-present",
|
|
419
|
+
errorExists: (pod) => {
|
|
420
|
+
var _a, _b;
|
|
421
|
+
return ((_b = (_a = pod.status) == null ? void 0 : _a.conditions) != null ? _b : []).some((c) => c.message !== void 0);
|
|
422
|
+
},
|
|
423
|
+
messageAccessor: (pod) => {
|
|
424
|
+
var _a, _b;
|
|
425
|
+
return ((_b = (_a = pod.status) == null ? void 0 : _a.conditions) != null ? _b : []).filter((c) => c.message !== void 0).map((c) => {
|
|
426
|
+
var _a2;
|
|
427
|
+
return (_a2 = c.message) != null ? _a2 : "";
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
severity: 6,
|
|
433
|
+
errorExplanation: "container-waiting",
|
|
434
|
+
errorExists: (pod) => {
|
|
435
|
+
var _a, _b;
|
|
436
|
+
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).some((cs) => {
|
|
437
|
+
var _a2, _b2;
|
|
438
|
+
return ((_b2 = (_a2 = cs.state) == null ? void 0 : _a2.waiting) == null ? void 0 : _b2.message) !== void 0;
|
|
439
|
+
});
|
|
440
|
+
},
|
|
441
|
+
messageAccessor: (pod) => {
|
|
442
|
+
var _a, _b;
|
|
443
|
+
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).filter((cs) => {
|
|
444
|
+
var _a2, _b2;
|
|
445
|
+
return ((_b2 = (_a2 = cs.state) == null ? void 0 : _a2.waiting) == null ? void 0 : _b2.message) !== void 0;
|
|
446
|
+
}).map((cs) => {
|
|
447
|
+
var _a2, _b2, _c;
|
|
448
|
+
return (_c = (_b2 = (_a2 = cs.state) == null ? void 0 : _a2.waiting) == null ? void 0 : _b2.message) != null ? _c : "";
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
severity: 4,
|
|
454
|
+
errorExplanation: "container-last-state-error",
|
|
455
|
+
errorExists: (pod) => {
|
|
456
|
+
var _a, _b;
|
|
457
|
+
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).some((cs) => {
|
|
458
|
+
var _a2, _b2, _c;
|
|
459
|
+
return ((_c = (_b2 = (_a2 = cs.lastState) == null ? void 0 : _a2.terminated) == null ? void 0 : _b2.reason) != null ? _c : "") === "Error";
|
|
460
|
+
});
|
|
461
|
+
},
|
|
462
|
+
messageAccessor: (pod) => {
|
|
463
|
+
var _a, _b;
|
|
464
|
+
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).filter((cs) => {
|
|
465
|
+
var _a2, _b2, _c;
|
|
466
|
+
return ((_c = (_b2 = (_a2 = cs.lastState) == null ? void 0 : _a2.terminated) == null ? void 0 : _b2.reason) != null ? _c : "") === "Error";
|
|
467
|
+
}).map((cs) => {
|
|
468
|
+
var _a2, _b2;
|
|
469
|
+
return `container=${cs.name} exited with error code (${(_b2 = (_a2 = cs.lastState) == null ? void 0 : _a2.terminated) == null ? void 0 : _b2.exitCode})`;
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
];
|
|
474
|
+
const detectErrorsInPods = (pods, clusterName) => detectErrorsInObjects(pods, "Pod", clusterName, podErrorMappers);
|
|
475
|
+
|
|
476
|
+
const deploymentErrorMappers = [
|
|
477
|
+
{
|
|
478
|
+
severity: 6,
|
|
479
|
+
errorExplanation: "condition-message-present",
|
|
480
|
+
errorExists: (deployment) => {
|
|
481
|
+
var _a, _b;
|
|
482
|
+
return ((_b = (_a = deployment.status) == null ? void 0 : _a.conditions) != null ? _b : []).filter((c) => c.status === "False").some((c) => c.message !== void 0);
|
|
483
|
+
},
|
|
484
|
+
messageAccessor: (deployment) => {
|
|
485
|
+
var _a, _b;
|
|
486
|
+
return ((_b = (_a = deployment.status) == null ? void 0 : _a.conditions) != null ? _b : []).filter((c) => c.status === "False").filter((c) => c.message !== void 0).map((c) => {
|
|
487
|
+
var _a2;
|
|
488
|
+
return (_a2 = c.message) != null ? _a2 : "";
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
];
|
|
493
|
+
const detectErrorsInDeployments = (deployments, clusterName) => detectErrorsInObjects(deployments, "Deployment", clusterName, deploymentErrorMappers);
|
|
494
|
+
|
|
495
|
+
const hpaErrorMappers = [
|
|
496
|
+
{
|
|
497
|
+
severity: 8,
|
|
498
|
+
errorExplanation: "hpa-max-current-replicas",
|
|
499
|
+
errorExists: (hpa) => {
|
|
500
|
+
var _a, _b, _c;
|
|
501
|
+
return ((_b = (_a = hpa.spec) == null ? void 0 : _a.maxReplicas) != null ? _b : -1) === ((_c = hpa.status) == null ? void 0 : _c.currentReplicas);
|
|
502
|
+
},
|
|
503
|
+
messageAccessor: (hpa) => {
|
|
504
|
+
var _a, _b, _c;
|
|
505
|
+
return [
|
|
506
|
+
`Current number of replicas (${(_a = hpa.status) == null ? void 0 : _a.currentReplicas}) is equal to the configured max number of replicas (${(_c = (_b = hpa.spec) == null ? void 0 : _b.maxReplicas) != null ? _c : -1})`
|
|
507
|
+
];
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
];
|
|
511
|
+
const detectErrorsInHpa = (hpas, clusterName) => detectErrorsInObjects(hpas, "HorizontalPodAutoscaler", clusterName, hpaErrorMappers);
|
|
512
|
+
|
|
513
|
+
const detectErrors = (objects) => {
|
|
514
|
+
const errors = new Map();
|
|
515
|
+
for (const clusterResponse of objects.items) {
|
|
516
|
+
let clusterErrors = [];
|
|
517
|
+
const groupedResponses = groupResponses(clusterResponse.resources);
|
|
518
|
+
clusterErrors = clusterErrors.concat(detectErrorsInPods(groupedResponses.pods, clusterResponse.cluster.name));
|
|
519
|
+
clusterErrors = clusterErrors.concat(detectErrorsInDeployments(groupedResponses.deployments, clusterResponse.cluster.name));
|
|
520
|
+
clusterErrors = clusterErrors.concat(detectErrorsInHpa(groupedResponses.horizontalPodAutoscalers, clusterResponse.cluster.name));
|
|
521
|
+
errors.set(clusterResponse.cluster.name, clusterErrors);
|
|
522
|
+
}
|
|
523
|
+
return errors;
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
const useKubernetesObjects = (entity, intervalMs = 1e4) => {
|
|
527
|
+
const kubernetesApi = useApi(kubernetesApiRef);
|
|
528
|
+
const kubernetesAuthProvidersApi = useApi(kubernetesAuthProvidersApiRef);
|
|
529
|
+
const [kubernetesObjects, setKubernetesObjects] = useState(void 0);
|
|
530
|
+
const [error, setError] = useState(void 0);
|
|
531
|
+
const getObjects = async () => {
|
|
532
|
+
let clusters = [];
|
|
533
|
+
try {
|
|
534
|
+
clusters = await kubernetesApi.getClusters();
|
|
535
|
+
} catch (e) {
|
|
536
|
+
setError(e.message);
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const authProviders = [
|
|
540
|
+
...new Set(clusters.map((c) => c.authProvider))
|
|
541
|
+
];
|
|
542
|
+
let requestBody = {
|
|
543
|
+
entity
|
|
544
|
+
};
|
|
545
|
+
for (const authProviderStr of authProviders) {
|
|
546
|
+
try {
|
|
547
|
+
requestBody = await kubernetesAuthProvidersApi.decorateRequestBodyForAuth(authProviderStr, requestBody);
|
|
548
|
+
} catch (e) {
|
|
549
|
+
setError(e.message);
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
try {
|
|
554
|
+
setKubernetesObjects(await kubernetesApi.getObjectsByEntity(requestBody));
|
|
555
|
+
} catch (e) {
|
|
556
|
+
setError(e.message);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
useEffect(() => {
|
|
561
|
+
getObjects();
|
|
562
|
+
}, [entity.metadata.name, kubernetesApi, kubernetesAuthProvidersApi]);
|
|
563
|
+
useInterval(() => {
|
|
564
|
+
getObjects();
|
|
565
|
+
}, intervalMs);
|
|
566
|
+
return {
|
|
567
|
+
kubernetesObjects,
|
|
568
|
+
error
|
|
569
|
+
};
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const PodNamesWithErrorsContext = React__default.createContext(new Set());
|
|
573
|
+
|
|
574
|
+
const GroupedResponsesContext = React__default.createContext({
|
|
575
|
+
pods: [],
|
|
576
|
+
replicaSets: [],
|
|
577
|
+
deployments: [],
|
|
578
|
+
services: [],
|
|
579
|
+
configMaps: [],
|
|
580
|
+
horizontalPodAutoscalers: [],
|
|
581
|
+
ingresses: [],
|
|
582
|
+
customResources: []
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
const ClusterContext = React__default.createContext({
|
|
586
|
+
name: ""
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
const kindMappings$1 = {
|
|
590
|
+
deployment: "deployment",
|
|
591
|
+
ingress: "ingress",
|
|
592
|
+
service: "service",
|
|
593
|
+
horizontalpodautoscaler: "deployment"
|
|
594
|
+
};
|
|
595
|
+
function standardFormatter(options) {
|
|
596
|
+
var _a, _b;
|
|
597
|
+
const result = new URL(options.dashboardUrl.href);
|
|
598
|
+
const name = (_a = options.object.metadata) == null ? void 0 : _a.name;
|
|
599
|
+
const namespace = (_b = options.object.metadata) == null ? void 0 : _b.namespace;
|
|
600
|
+
const validKind = kindMappings$1[options.kind.toLocaleLowerCase("en-US")];
|
|
601
|
+
if (namespace) {
|
|
602
|
+
result.searchParams.set("namespace", namespace);
|
|
603
|
+
}
|
|
604
|
+
if (validKind && name && namespace) {
|
|
605
|
+
result.hash = `/${validKind}/${namespace}/${name}`;
|
|
606
|
+
} else if (namespace) {
|
|
607
|
+
result.hash = "/workloads";
|
|
608
|
+
}
|
|
609
|
+
return result;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
const kindMappings = {
|
|
613
|
+
deployment: "apps.deployment",
|
|
614
|
+
ingress: "networking.k8s.io.ingress",
|
|
615
|
+
service: "service",
|
|
616
|
+
horizontalpodautoscaler: "autoscaling.horizontalpodautoscaler"
|
|
617
|
+
};
|
|
618
|
+
function rancherFormatter(options) {
|
|
619
|
+
var _a, _b;
|
|
620
|
+
const result = new URL(options.dashboardUrl.href);
|
|
621
|
+
const name = (_a = options.object.metadata) == null ? void 0 : _a.name;
|
|
622
|
+
const namespace = (_b = options.object.metadata) == null ? void 0 : _b.namespace;
|
|
623
|
+
const validKind = kindMappings[options.kind.toLocaleLowerCase("en-US")];
|
|
624
|
+
if (validKind && name && namespace) {
|
|
625
|
+
result.pathname += `explorer/${validKind}/${namespace}/${name}`;
|
|
626
|
+
} else if (namespace) {
|
|
627
|
+
result.pathname += "explorer/workload";
|
|
628
|
+
}
|
|
629
|
+
return result;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
function openshiftFormatter(_options) {
|
|
633
|
+
throw new Error("OpenShift formatter is not yet implemented. Please, contribute!");
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
function aksFormatter(_options) {
|
|
637
|
+
throw new Error("AKS formatter is not yet implemented. Please, contribute!");
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function eksFormatter(_options) {
|
|
641
|
+
throw new Error("EKS formatter is not yet implemented. Please, contribute!");
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
function gkeFormatter(_options) {
|
|
645
|
+
throw new Error("GKE formatter is not yet implemented. Please, contribute!");
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
const clusterLinksFormatters = {
|
|
649
|
+
standard: standardFormatter,
|
|
650
|
+
rancher: rancherFormatter,
|
|
651
|
+
openshift: openshiftFormatter,
|
|
652
|
+
aks: aksFormatter,
|
|
653
|
+
eks: eksFormatter,
|
|
654
|
+
gke: gkeFormatter
|
|
655
|
+
};
|
|
656
|
+
const defaultFormatterName = "standard";
|
|
657
|
+
|
|
658
|
+
function formatClusterLink(options) {
|
|
659
|
+
if (!options.dashboardUrl) {
|
|
660
|
+
return void 0;
|
|
661
|
+
}
|
|
662
|
+
if (!options.object) {
|
|
663
|
+
return options.dashboardUrl;
|
|
664
|
+
}
|
|
381
665
|
const app = options.dashboardApp || defaultFormatterName;
|
|
382
666
|
const formatter = clusterLinksFormatters[app];
|
|
383
667
|
if (!formatter) {
|
|
@@ -590,7 +874,7 @@ const PodDrawer = ({
|
|
|
590
874
|
});
|
|
591
875
|
};
|
|
592
876
|
|
|
593
|
-
const columns
|
|
877
|
+
const columns = [
|
|
594
878
|
{
|
|
595
879
|
title: "name",
|
|
596
880
|
highlight: true,
|
|
@@ -600,516 +884,237 @@ const columns$1 = [
|
|
|
600
884
|
},
|
|
601
885
|
{
|
|
602
886
|
title: "phase",
|
|
603
|
-
render: (pod) => {
|
|
604
|
-
var _a, _b;
|
|
605
|
-
return (_b = (_a = pod.status) == null ? void 0 : _a.phase) != null ? _b : "unknown";
|
|
606
|
-
}
|
|
607
|
-
},
|
|
608
|
-
{
|
|
609
|
-
title: "containers ready",
|
|
610
|
-
align: "center",
|
|
611
|
-
render: containersReady
|
|
612
|
-
},
|
|
613
|
-
{
|
|
614
|
-
title: "total restarts",
|
|
615
|
-
align: "center",
|
|
616
|
-
render: totalRestarts,
|
|
617
|
-
type: "numeric"
|
|
618
|
-
},
|
|
619
|
-
{
|
|
620
|
-
title: "status",
|
|
621
|
-
render: containerStatuses
|
|
622
|
-
}
|
|
623
|
-
];
|
|
624
|
-
const PodsTable = ({pods}) => {
|
|
625
|
-
const tableStyle = {
|
|
626
|
-
minWidth: "0",
|
|
627
|
-
width: "100%"
|
|
628
|
-
};
|
|
629
|
-
return /* @__PURE__ */ React__default.createElement("div", {
|
|
630
|
-
style: tableStyle
|
|
631
|
-
}, /* @__PURE__ */ React__default.createElement(Table, {
|
|
632
|
-
options: {paging: true, search: false},
|
|
633
|
-
data: pods,
|
|
634
|
-
columns: columns$1
|
|
635
|
-
}));
|
|
636
|
-
};
|
|
637
|
-
|
|
638
|
-
const DeploymentDrawer = ({
|
|
639
|
-
deployment,
|
|
640
|
-
expanded
|
|
641
|
-
}) => {
|
|
642
|
-
var _a, _b, _c;
|
|
643
|
-
const namespace = (_a = deployment.metadata) == null ? void 0 : _a.namespace;
|
|
644
|
-
return /* @__PURE__ */ React__default.createElement(KubernetesDrawer, {
|
|
645
|
-
object: deployment,
|
|
646
|
-
expanded,
|
|
647
|
-
kind: "Deployment",
|
|
648
|
-
renderObject: (deploymentObj) => {
|
|
649
|
-
var _a2, _b2, _c2, _d, _e, _f, _g, _h;
|
|
650
|
-
const conditions = ((_b2 = (_a2 = deploymentObj.status) == null ? void 0 : _a2.conditions) != null ? _b2 : []).map(renderCondition).reduce((accum, next) => {
|
|
651
|
-
accum[next[0]] = next[1];
|
|
652
|
-
return accum;
|
|
653
|
-
}, {});
|
|
654
|
-
return {
|
|
655
|
-
strategy: (_d = (_c2 = deploymentObj.spec) == null ? void 0 : _c2.strategy) != null ? _d : "???",
|
|
656
|
-
minReadySeconds: (_f = (_e = deploymentObj.spec) == null ? void 0 : _e.minReadySeconds) != null ? _f : "???",
|
|
657
|
-
progressDeadlineSeconds: (_h = (_g = deploymentObj.spec) == null ? void 0 : _g.progressDeadlineSeconds) != null ? _h : "???",
|
|
658
|
-
...conditions
|
|
659
|
-
};
|
|
660
|
-
}
|
|
661
|
-
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
662
|
-
container: true,
|
|
663
|
-
direction: "column",
|
|
664
|
-
justifyContent: "flex-start",
|
|
665
|
-
alignItems: "flex-start",
|
|
666
|
-
spacing: 0
|
|
667
|
-
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
668
|
-
item: true
|
|
669
|
-
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
670
|
-
variant: "h5"
|
|
671
|
-
}, (_c = (_b = deployment.metadata) == null ? void 0 : _b.name) != null ? _c : "unknown object")), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
672
|
-
item: true
|
|
673
|
-
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
674
|
-
color: "textSecondary",
|
|
675
|
-
variant: "body1"
|
|
676
|
-
}, "Deployment")), namespace && /* @__PURE__ */ React__default.createElement(Grid, {
|
|
677
|
-
item: true
|
|
678
|
-
}, /* @__PURE__ */ React__default.createElement(Chip, {
|
|
679
|
-
size: "small",
|
|
680
|
-
label: `namespace: ${namespace}`
|
|
681
|
-
}))));
|
|
682
|
-
};
|
|
683
|
-
|
|
684
|
-
const HorizontalPodAutoscalerDrawer = ({
|
|
685
|
-
hpa,
|
|
686
|
-
expanded,
|
|
687
|
-
children
|
|
688
|
-
}) => {
|
|
689
|
-
return /* @__PURE__ */ React__default.createElement(KubernetesDrawer, {
|
|
690
|
-
kind: "HorizontalPodAutoscaler",
|
|
691
|
-
object: hpa,
|
|
692
|
-
expanded,
|
|
693
|
-
renderObject: (hpaObject) => {
|
|
694
|
-
var _a, _b, _c, _d, _e, _f;
|
|
695
|
-
return {
|
|
696
|
-
targetCPUUtilizationPercentage: (_a = hpaObject.spec) == null ? void 0 : _a.targetCPUUtilizationPercentage,
|
|
697
|
-
currentCPUUtilizationPercentage: (_b = hpaObject.status) == null ? void 0 : _b.currentCPUUtilizationPercentage,
|
|
698
|
-
minReplicas: (_c = hpaObject.spec) == null ? void 0 : _c.minReplicas,
|
|
699
|
-
maxReplicas: (_d = hpaObject.spec) == null ? void 0 : _d.maxReplicas,
|
|
700
|
-
currentReplicas: (_e = hpaObject.status) == null ? void 0 : _e.currentReplicas,
|
|
701
|
-
desiredReplicas: (_f = hpaObject.status) == null ? void 0 : _f.desiredReplicas
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
|
-
}, children);
|
|
705
|
-
};
|
|
706
|
-
|
|
707
|
-
function getOwnedResources(potentialOwner, possiblyOwned) {
|
|
708
|
-
return possiblyOwned.filter((p) => {
|
|
709
|
-
var _a, _b, _c;
|
|
710
|
-
return (_c = (_b = (_a = p.metadata) == null ? void 0 : _a.ownerReferences) == null ? void 0 : _b.some((o) => {
|
|
711
|
-
var _a2;
|
|
712
|
-
return o.uid === ((_a2 = potentialOwner.metadata) == null ? void 0 : _a2.uid);
|
|
713
|
-
})) != null ? _c : false;
|
|
714
|
-
});
|
|
715
|
-
}
|
|
716
|
-
const getOwnedPodsThroughReplicaSets = (potentialOwner, replicaSets, pods) => {
|
|
717
|
-
return getOwnedResources(potentialOwner, replicaSets.filter((rs) => rs.status && rs.status.replicas > 0)).reduce((accum, rs) => {
|
|
718
|
-
return accum.concat(getOwnedResources(rs, pods));
|
|
719
|
-
}, []);
|
|
720
|
-
};
|
|
721
|
-
const getMatchingHpa = (ownerName, ownerKind, hpas) => {
|
|
722
|
-
return hpas.find((hpa) => {
|
|
723
|
-
var _a, _b, _c, _d, _e, _f;
|
|
724
|
-
return ((_c = (_b = (_a = hpa.spec) == null ? void 0 : _a.scaleTargetRef) == null ? void 0 : _b.kind) != null ? _c : "").toLocaleLowerCase("en-US") === ownerKind.toLocaleLowerCase("en-US") && ((_f = (_e = (_d = hpa.spec) == null ? void 0 : _d.scaleTargetRef) == null ? void 0 : _e.name) != null ? _f : "") === (ownerName != null ? ownerName : "unknown-deployment");
|
|
725
|
-
});
|
|
726
|
-
};
|
|
727
|
-
|
|
728
|
-
const DeploymentSummary = ({
|
|
729
|
-
deployment,
|
|
730
|
-
numberOfCurrentPods,
|
|
731
|
-
numberOfPodsWithErrors,
|
|
732
|
-
hpa
|
|
733
|
-
}) => {
|
|
734
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
735
|
-
return /* @__PURE__ */ React__default.createElement(Grid, {
|
|
736
|
-
container: true,
|
|
737
|
-
direction: "row",
|
|
738
|
-
justifyContent: "flex-start",
|
|
739
|
-
alignItems: "center"
|
|
740
|
-
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
741
|
-
xs: 3,
|
|
742
|
-
item: true
|
|
743
|
-
}, /* @__PURE__ */ React__default.createElement(DeploymentDrawer, {
|
|
744
|
-
deployment
|
|
745
|
-
})), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
746
|
-
item: true,
|
|
747
|
-
xs: 1
|
|
748
|
-
}, /* @__PURE__ */ React__default.createElement(Divider, {
|
|
749
|
-
style: {height: "5em"},
|
|
750
|
-
orientation: "vertical"
|
|
751
|
-
})), hpa && /* @__PURE__ */ React__default.createElement(Grid, {
|
|
752
|
-
item: true,
|
|
753
|
-
xs: 3
|
|
754
|
-
}, /* @__PURE__ */ React__default.createElement(HorizontalPodAutoscalerDrawer, {
|
|
755
|
-
hpa
|
|
756
|
-
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
757
|
-
item: true,
|
|
758
|
-
container: true,
|
|
759
|
-
direction: "column",
|
|
760
|
-
justifyContent: "flex-start",
|
|
761
|
-
alignItems: "flex-start",
|
|
762
|
-
spacing: 0
|
|
763
|
-
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
764
|
-
item: true
|
|
765
|
-
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
766
|
-
variant: "subtitle2"
|
|
767
|
-
}, "min replicas ", (_b = (_a = hpa.spec) == null ? void 0 : _a.minReplicas) != null ? _b : "?", " / max replicas", " ", (_d = (_c = hpa.spec) == null ? void 0 : _c.maxReplicas) != null ? _d : "?")), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
768
|
-
item: true
|
|
769
|
-
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
770
|
-
variant: "subtitle2"
|
|
771
|
-
}, "current CPU usage:", " ", (_f = (_e = hpa.status) == null ? void 0 : _e.currentCPUUtilizationPercentage) != null ? _f : "?", "%")), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
772
|
-
item: true
|
|
773
|
-
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
774
|
-
variant: "subtitle2"
|
|
775
|
-
}, "target CPU usage:", " ", (_h = (_g = hpa.spec) == null ? void 0 : _g.targetCPUUtilizationPercentage) != null ? _h : "?", "%"))))), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
776
|
-
item: true,
|
|
777
|
-
container: true,
|
|
778
|
-
xs: 3,
|
|
779
|
-
direction: "column",
|
|
780
|
-
justifyContent: "flex-start",
|
|
781
|
-
alignItems: "flex-start"
|
|
782
|
-
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
783
|
-
item: true
|
|
784
|
-
}, /* @__PURE__ */ React__default.createElement(StatusOK, null, numberOfCurrentPods, " pods")), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
785
|
-
item: true
|
|
786
|
-
}, numberOfPodsWithErrors > 0 ? /* @__PURE__ */ React__default.createElement(StatusError, null, numberOfPodsWithErrors, " pod", numberOfPodsWithErrors > 1 ? "s" : "", " with errors") : /* @__PURE__ */ React__default.createElement(StatusOK, null, "No pods with errors"))));
|
|
787
|
-
};
|
|
788
|
-
const DeploymentAccordion = ({
|
|
789
|
-
deployment,
|
|
790
|
-
ownedPods,
|
|
791
|
-
matchingHpa
|
|
792
|
-
}) => {
|
|
793
|
-
const podNamesWithErrors = useContext(PodNamesWithErrorsContext);
|
|
794
|
-
const podsWithErrors = ownedPods.filter((p) => {
|
|
795
|
-
var _a, _b;
|
|
796
|
-
return podNamesWithErrors.has((_b = (_a = p.metadata) == null ? void 0 : _a.name) != null ? _b : "");
|
|
797
|
-
});
|
|
798
|
-
return /* @__PURE__ */ React__default.createElement(Accordion, {
|
|
799
|
-
TransitionProps: {unmountOnExit: true}
|
|
800
|
-
}, /* @__PURE__ */ React__default.createElement(AccordionSummary, {
|
|
801
|
-
expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null)
|
|
802
|
-
}, /* @__PURE__ */ React__default.createElement(DeploymentSummary, {
|
|
803
|
-
deployment,
|
|
804
|
-
numberOfCurrentPods: ownedPods.length,
|
|
805
|
-
numberOfPodsWithErrors: podsWithErrors.length,
|
|
806
|
-
hpa: matchingHpa
|
|
807
|
-
})), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(PodsTable, {
|
|
808
|
-
pods: ownedPods
|
|
809
|
-
})));
|
|
810
|
-
};
|
|
811
|
-
const DeploymentsAccordions = ({}) => {
|
|
812
|
-
const groupedResponses = useContext(GroupedResponsesContext);
|
|
813
|
-
return /* @__PURE__ */ React__default.createElement(Grid, {
|
|
814
|
-
container: true,
|
|
815
|
-
direction: "column",
|
|
816
|
-
justifyContent: "flex-start",
|
|
817
|
-
alignItems: "flex-start"
|
|
818
|
-
}, groupedResponses.deployments.map((deployment, i) => {
|
|
819
|
-
var _a;
|
|
820
|
-
return /* @__PURE__ */ React__default.createElement(Grid, {
|
|
821
|
-
container: true,
|
|
822
|
-
item: true,
|
|
823
|
-
key: i,
|
|
824
|
-
xs: true
|
|
825
|
-
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
826
|
-
item: true,
|
|
827
|
-
xs: true
|
|
828
|
-
}, /* @__PURE__ */ React__default.createElement(DeploymentAccordion, {
|
|
829
|
-
matchingHpa: getMatchingHpa((_a = deployment.metadata) == null ? void 0 : _a.name, "deployment", groupedResponses.horizontalPodAutoscalers),
|
|
830
|
-
ownedPods: getOwnedPodsThroughReplicaSets(deployment, groupedResponses.replicaSets, groupedResponses.pods),
|
|
831
|
-
deployment
|
|
832
|
-
})));
|
|
833
|
-
}));
|
|
834
|
-
};
|
|
835
|
-
|
|
836
|
-
const columns = [
|
|
837
|
-
{
|
|
838
|
-
title: "cluster",
|
|
839
|
-
width: "15%",
|
|
840
|
-
render: (detectedError) => detectedError.cluster
|
|
841
|
-
},
|
|
842
|
-
{
|
|
843
|
-
title: "kind",
|
|
844
|
-
width: "15%",
|
|
845
|
-
render: (detectedError) => detectedError.kind
|
|
846
|
-
},
|
|
847
|
-
{
|
|
848
|
-
title: "name",
|
|
849
|
-
width: "30%",
|
|
850
|
-
render: (detectedError) => {
|
|
851
|
-
const errorCount = detectedError.names.length;
|
|
852
|
-
if (errorCount === 0) {
|
|
853
|
-
return null;
|
|
854
|
-
}
|
|
855
|
-
const displayName = detectedError.names[0];
|
|
856
|
-
const otherErrorCount = errorCount - 1;
|
|
857
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, displayName, " ", otherErrorCount > 0 && /* @__PURE__ */ React.createElement(Chip, {
|
|
858
|
-
label: `+ ${otherErrorCount} other${otherErrorCount > 1 ? "s" : ""}`,
|
|
859
|
-
size: "small"
|
|
860
|
-
}));
|
|
861
|
-
}
|
|
862
|
-
},
|
|
863
|
-
{
|
|
864
|
-
title: "messages",
|
|
865
|
-
width: "40%",
|
|
866
|
-
render: (detectedError) => /* @__PURE__ */ React.createElement(React.Fragment, null, detectedError.message.map((m, i) => /* @__PURE__ */ React.createElement("div", {
|
|
867
|
-
key: i
|
|
868
|
-
}, m)))
|
|
869
|
-
}
|
|
870
|
-
];
|
|
871
|
-
const sortBySeverity = (a, b) => {
|
|
872
|
-
if (a.severity < b.severity) {
|
|
873
|
-
return 1;
|
|
874
|
-
} else if (b.severity < a.severity) {
|
|
875
|
-
return -1;
|
|
876
|
-
}
|
|
877
|
-
return 0;
|
|
878
|
-
};
|
|
879
|
-
const ErrorEmptyState = () => {
|
|
880
|
-
return /* @__PURE__ */ React.createElement(Grid, {
|
|
881
|
-
container: true,
|
|
882
|
-
justifyContent: "space-around",
|
|
883
|
-
direction: "row",
|
|
884
|
-
alignItems: "center",
|
|
885
|
-
spacing: 2
|
|
886
|
-
}, /* @__PURE__ */ React.createElement(Grid, {
|
|
887
|
-
item: true,
|
|
888
|
-
xs: 4
|
|
889
|
-
}, /* @__PURE__ */ React.createElement(Typography, {
|
|
890
|
-
variant: "h5"
|
|
891
|
-
}, "Nice! There are no errors to report!")), /* @__PURE__ */ React.createElement(Grid, {
|
|
892
|
-
item: true,
|
|
893
|
-
xs: 4
|
|
894
|
-
}, /* @__PURE__ */ React.createElement("img", {
|
|
895
|
-
src: EmptyStateImage,
|
|
896
|
-
alt: "EmptyState",
|
|
897
|
-
"data-testid": "emptyStateImg"
|
|
898
|
-
})));
|
|
899
|
-
};
|
|
900
|
-
const ErrorReporting = ({detectedErrors}) => {
|
|
901
|
-
const errors = Array.from(detectedErrors.values()).flat().sort(sortBySeverity);
|
|
902
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, errors.length === 0 ? /* @__PURE__ */ React.createElement(InfoCard, {
|
|
903
|
-
title: "Error Reporting"
|
|
904
|
-
}, /* @__PURE__ */ React.createElement(ErrorEmptyState, null)) : /* @__PURE__ */ React.createElement(Table, {
|
|
905
|
-
title: "Error Reporting",
|
|
906
|
-
data: errors,
|
|
907
|
-
columns,
|
|
908
|
-
options: {paging: true, search: false}
|
|
909
|
-
}));
|
|
910
|
-
};
|
|
911
|
-
|
|
912
|
-
const groupResponses = (fetchResponse) => {
|
|
913
|
-
return fetchResponse.reduce((prev, next) => {
|
|
914
|
-
switch (next.type) {
|
|
915
|
-
case "deployments":
|
|
916
|
-
prev.deployments.push(...next.resources);
|
|
917
|
-
break;
|
|
918
|
-
case "pods":
|
|
919
|
-
prev.pods.push(...next.resources);
|
|
920
|
-
break;
|
|
921
|
-
case "replicasets":
|
|
922
|
-
prev.replicaSets.push(...next.resources);
|
|
923
|
-
break;
|
|
924
|
-
case "services":
|
|
925
|
-
prev.services.push(...next.resources);
|
|
926
|
-
break;
|
|
927
|
-
case "configmaps":
|
|
928
|
-
prev.configMaps.push(...next.resources);
|
|
929
|
-
break;
|
|
930
|
-
case "horizontalpodautoscalers":
|
|
931
|
-
prev.horizontalPodAutoscalers.push(...next.resources);
|
|
932
|
-
break;
|
|
933
|
-
case "ingresses":
|
|
934
|
-
prev.ingresses.push(...next.resources);
|
|
935
|
-
break;
|
|
936
|
-
case "customresources":
|
|
937
|
-
prev.customResources.push(...next.resources);
|
|
938
|
-
break;
|
|
939
|
-
}
|
|
940
|
-
return prev;
|
|
941
|
-
}, {
|
|
942
|
-
pods: [],
|
|
943
|
-
replicaSets: [],
|
|
944
|
-
deployments: [],
|
|
945
|
-
services: [],
|
|
946
|
-
configMaps: [],
|
|
947
|
-
horizontalPodAutoscalers: [],
|
|
948
|
-
ingresses: [],
|
|
949
|
-
customResources: []
|
|
950
|
-
});
|
|
951
|
-
};
|
|
952
|
-
|
|
953
|
-
const detectErrorsInObjects = (objects, kind, clusterName, errorMappers) => {
|
|
954
|
-
var _a, _b;
|
|
955
|
-
const errors = new Map();
|
|
956
|
-
for (const object of objects) {
|
|
957
|
-
for (const errorMapper of errorMappers) {
|
|
958
|
-
if (errorMapper.errorExists(object)) {
|
|
959
|
-
const message = errorMapper.messageAccessor(object);
|
|
960
|
-
const dedupKey = message.join("");
|
|
961
|
-
const value = errors.get(dedupKey);
|
|
962
|
-
const name = (_b = (_a = object.metadata) == null ? void 0 : _a.name) != null ? _b : "unknown";
|
|
963
|
-
if (value !== void 0) {
|
|
964
|
-
value.names.push(name);
|
|
965
|
-
errors.set(dedupKey, value);
|
|
966
|
-
} else {
|
|
967
|
-
errors.set(dedupKey, {
|
|
968
|
-
cluster: clusterName,
|
|
969
|
-
kind,
|
|
970
|
-
names: [name],
|
|
971
|
-
message,
|
|
972
|
-
severity: errorMapper.severity
|
|
973
|
-
});
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
return Array.from(errors.values());
|
|
979
|
-
};
|
|
980
|
-
|
|
981
|
-
const podErrorMappers = [
|
|
982
|
-
{
|
|
983
|
-
severity: 5,
|
|
984
|
-
errorExplanation: "status-message",
|
|
985
|
-
errorExists: (pod) => {
|
|
986
|
-
var _a;
|
|
987
|
-
return ((_a = pod.status) == null ? void 0 : _a.message) !== void 0;
|
|
988
|
-
},
|
|
989
|
-
messageAccessor: (pod) => {
|
|
990
|
-
var _a, _b;
|
|
991
|
-
return [(_b = (_a = pod.status) == null ? void 0 : _a.message) != null ? _b : ""];
|
|
992
|
-
}
|
|
993
|
-
},
|
|
994
|
-
{
|
|
995
|
-
severity: 4,
|
|
996
|
-
errorExplanation: "containers-restarting",
|
|
997
|
-
errorExists: (pod) => {
|
|
998
|
-
return totalRestarts(pod) > 3;
|
|
999
|
-
},
|
|
1000
|
-
messageAccessor: (pod) => {
|
|
1001
|
-
var _a, _b;
|
|
1002
|
-
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).filter((cs) => cs.restartCount > 0).map((cs) => `container=${cs.name} restarted ${cs.restartCount} times`);
|
|
1003
|
-
}
|
|
1004
|
-
},
|
|
1005
|
-
{
|
|
1006
|
-
severity: 5,
|
|
1007
|
-
errorExplanation: "condition-message-present",
|
|
1008
|
-
errorExists: (pod) => {
|
|
1009
|
-
var _a, _b;
|
|
1010
|
-
return ((_b = (_a = pod.status) == null ? void 0 : _a.conditions) != null ? _b : []).some((c) => c.message !== void 0);
|
|
1011
|
-
},
|
|
1012
|
-
messageAccessor: (pod) => {
|
|
1013
|
-
var _a, _b;
|
|
1014
|
-
return ((_b = (_a = pod.status) == null ? void 0 : _a.conditions) != null ? _b : []).filter((c) => c.message !== void 0).map((c) => {
|
|
1015
|
-
var _a2;
|
|
1016
|
-
return (_a2 = c.message) != null ? _a2 : "";
|
|
1017
|
-
});
|
|
1018
|
-
}
|
|
1019
|
-
},
|
|
1020
|
-
{
|
|
1021
|
-
severity: 6,
|
|
1022
|
-
errorExplanation: "container-waiting",
|
|
1023
|
-
errorExists: (pod) => {
|
|
1024
|
-
var _a, _b;
|
|
1025
|
-
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).some((cs) => {
|
|
1026
|
-
var _a2, _b2;
|
|
1027
|
-
return ((_b2 = (_a2 = cs.state) == null ? void 0 : _a2.waiting) == null ? void 0 : _b2.message) !== void 0;
|
|
1028
|
-
});
|
|
1029
|
-
},
|
|
1030
|
-
messageAccessor: (pod) => {
|
|
1031
|
-
var _a, _b;
|
|
1032
|
-
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).filter((cs) => {
|
|
1033
|
-
var _a2, _b2;
|
|
1034
|
-
return ((_b2 = (_a2 = cs.state) == null ? void 0 : _a2.waiting) == null ? void 0 : _b2.message) !== void 0;
|
|
1035
|
-
}).map((cs) => {
|
|
1036
|
-
var _a2, _b2, _c;
|
|
1037
|
-
return (_c = (_b2 = (_a2 = cs.state) == null ? void 0 : _a2.waiting) == null ? void 0 : _b2.message) != null ? _c : "";
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
},
|
|
1041
|
-
{
|
|
1042
|
-
severity: 4,
|
|
1043
|
-
errorExplanation: "container-last-state-error",
|
|
1044
|
-
errorExists: (pod) => {
|
|
1045
|
-
var _a, _b;
|
|
1046
|
-
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).some((cs) => {
|
|
1047
|
-
var _a2, _b2, _c;
|
|
1048
|
-
return ((_c = (_b2 = (_a2 = cs.lastState) == null ? void 0 : _a2.terminated) == null ? void 0 : _b2.reason) != null ? _c : "") === "Error";
|
|
1049
|
-
});
|
|
1050
|
-
},
|
|
1051
|
-
messageAccessor: (pod) => {
|
|
1052
|
-
var _a, _b;
|
|
1053
|
-
return ((_b = (_a = pod.status) == null ? void 0 : _a.containerStatuses) != null ? _b : []).filter((cs) => {
|
|
1054
|
-
var _a2, _b2, _c;
|
|
1055
|
-
return ((_c = (_b2 = (_a2 = cs.lastState) == null ? void 0 : _a2.terminated) == null ? void 0 : _b2.reason) != null ? _c : "") === "Error";
|
|
1056
|
-
}).map((cs) => {
|
|
1057
|
-
var _a2, _b2;
|
|
1058
|
-
return `container=${cs.name} exited with error code (${(_b2 = (_a2 = cs.lastState) == null ? void 0 : _a2.terminated) == null ? void 0 : _b2.exitCode})`;
|
|
1059
|
-
});
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
];
|
|
1063
|
-
const detectErrorsInPods = (pods, clusterName) => detectErrorsInObjects(pods, "Pod", clusterName, podErrorMappers);
|
|
1064
|
-
|
|
1065
|
-
const deploymentErrorMappers = [
|
|
1066
|
-
{
|
|
1067
|
-
severity: 6,
|
|
1068
|
-
errorExplanation: "condition-message-present",
|
|
1069
|
-
errorExists: (deployment) => {
|
|
1070
|
-
var _a, _b;
|
|
1071
|
-
return ((_b = (_a = deployment.status) == null ? void 0 : _a.conditions) != null ? _b : []).filter((c) => c.status === "False").some((c) => c.message !== void 0);
|
|
1072
|
-
},
|
|
1073
|
-
messageAccessor: (deployment) => {
|
|
887
|
+
render: (pod) => {
|
|
1074
888
|
var _a, _b;
|
|
1075
|
-
return (
|
|
1076
|
-
var _a2;
|
|
1077
|
-
return (_a2 = c.message) != null ? _a2 : "";
|
|
1078
|
-
});
|
|
889
|
+
return (_b = (_a = pod.status) == null ? void 0 : _a.phase) != null ? _b : "unknown";
|
|
1079
890
|
}
|
|
891
|
+
},
|
|
892
|
+
{
|
|
893
|
+
title: "containers ready",
|
|
894
|
+
align: "center",
|
|
895
|
+
render: containersReady
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
title: "total restarts",
|
|
899
|
+
align: "center",
|
|
900
|
+
render: totalRestarts,
|
|
901
|
+
type: "numeric"
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
title: "status",
|
|
905
|
+
render: containerStatuses
|
|
1080
906
|
}
|
|
1081
907
|
];
|
|
1082
|
-
const
|
|
908
|
+
const PodsTable = ({pods}) => {
|
|
909
|
+
const tableStyle = {
|
|
910
|
+
minWidth: "0",
|
|
911
|
+
width: "100%"
|
|
912
|
+
};
|
|
913
|
+
return /* @__PURE__ */ React__default.createElement("div", {
|
|
914
|
+
style: tableStyle
|
|
915
|
+
}, /* @__PURE__ */ React__default.createElement(Table, {
|
|
916
|
+
options: {paging: true, search: false},
|
|
917
|
+
data: pods,
|
|
918
|
+
columns
|
|
919
|
+
}));
|
|
920
|
+
};
|
|
1083
921
|
|
|
1084
|
-
const
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
]
|
|
922
|
+
const DeploymentDrawer = ({
|
|
923
|
+
deployment,
|
|
924
|
+
expanded
|
|
925
|
+
}) => {
|
|
926
|
+
var _a, _b, _c;
|
|
927
|
+
const namespace = (_a = deployment.metadata) == null ? void 0 : _a.namespace;
|
|
928
|
+
return /* @__PURE__ */ React__default.createElement(KubernetesDrawer, {
|
|
929
|
+
object: deployment,
|
|
930
|
+
expanded,
|
|
931
|
+
kind: "Deployment",
|
|
932
|
+
renderObject: (deploymentObj) => {
|
|
933
|
+
var _a2, _b2, _c2, _d, _e, _f, _g, _h;
|
|
934
|
+
const conditions = ((_b2 = (_a2 = deploymentObj.status) == null ? void 0 : _a2.conditions) != null ? _b2 : []).map(renderCondition).reduce((accum, next) => {
|
|
935
|
+
accum[next[0]] = next[1];
|
|
936
|
+
return accum;
|
|
937
|
+
}, {});
|
|
938
|
+
return {
|
|
939
|
+
strategy: (_d = (_c2 = deploymentObj.spec) == null ? void 0 : _c2.strategy) != null ? _d : "???",
|
|
940
|
+
minReadySeconds: (_f = (_e = deploymentObj.spec) == null ? void 0 : _e.minReadySeconds) != null ? _f : "???",
|
|
941
|
+
progressDeadlineSeconds: (_h = (_g = deploymentObj.spec) == null ? void 0 : _g.progressDeadlineSeconds) != null ? _h : "???",
|
|
942
|
+
...conditions
|
|
943
|
+
};
|
|
1097
944
|
}
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
|
|
945
|
+
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
946
|
+
container: true,
|
|
947
|
+
direction: "column",
|
|
948
|
+
justifyContent: "flex-start",
|
|
949
|
+
alignItems: "flex-start",
|
|
950
|
+
spacing: 0
|
|
951
|
+
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
952
|
+
item: true
|
|
953
|
+
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
954
|
+
variant: "h5"
|
|
955
|
+
}, (_c = (_b = deployment.metadata) == null ? void 0 : _b.name) != null ? _c : "unknown object")), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
956
|
+
item: true
|
|
957
|
+
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
958
|
+
color: "textSecondary",
|
|
959
|
+
variant: "body1"
|
|
960
|
+
}, "Deployment")), namespace && /* @__PURE__ */ React__default.createElement(Grid, {
|
|
961
|
+
item: true
|
|
962
|
+
}, /* @__PURE__ */ React__default.createElement(Chip, {
|
|
963
|
+
size: "small",
|
|
964
|
+
label: `namespace: ${namespace}`
|
|
965
|
+
}))));
|
|
966
|
+
};
|
|
1101
967
|
|
|
1102
|
-
const
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
968
|
+
const HorizontalPodAutoscalerDrawer = ({
|
|
969
|
+
hpa,
|
|
970
|
+
expanded,
|
|
971
|
+
children
|
|
972
|
+
}) => {
|
|
973
|
+
return /* @__PURE__ */ React__default.createElement(KubernetesDrawer, {
|
|
974
|
+
kind: "HorizontalPodAutoscaler",
|
|
975
|
+
object: hpa,
|
|
976
|
+
expanded,
|
|
977
|
+
renderObject: (hpaObject) => {
|
|
978
|
+
var _a, _b, _c, _d, _e, _f;
|
|
979
|
+
return {
|
|
980
|
+
targetCPUUtilizationPercentage: (_a = hpaObject.spec) == null ? void 0 : _a.targetCPUUtilizationPercentage,
|
|
981
|
+
currentCPUUtilizationPercentage: (_b = hpaObject.status) == null ? void 0 : _b.currentCPUUtilizationPercentage,
|
|
982
|
+
minReplicas: (_c = hpaObject.spec) == null ? void 0 : _c.minReplicas,
|
|
983
|
+
maxReplicas: (_d = hpaObject.spec) == null ? void 0 : _d.maxReplicas,
|
|
984
|
+
currentReplicas: (_e = hpaObject.status) == null ? void 0 : _e.currentReplicas,
|
|
985
|
+
desiredReplicas: (_f = hpaObject.status) == null ? void 0 : _f.desiredReplicas
|
|
986
|
+
};
|
|
987
|
+
}
|
|
988
|
+
}, children);
|
|
989
|
+
};
|
|
990
|
+
|
|
991
|
+
function getOwnedResources(potentialOwner, possiblyOwned) {
|
|
992
|
+
return possiblyOwned.filter((p) => {
|
|
993
|
+
var _a, _b, _c;
|
|
994
|
+
return (_c = (_b = (_a = p.metadata) == null ? void 0 : _a.ownerReferences) == null ? void 0 : _b.some((o) => {
|
|
995
|
+
var _a2;
|
|
996
|
+
return o.uid === ((_a2 = potentialOwner.metadata) == null ? void 0 : _a2.uid);
|
|
997
|
+
})) != null ? _c : false;
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
const getOwnedPodsThroughReplicaSets = (potentialOwner, replicaSets, pods) => {
|
|
1001
|
+
return getOwnedResources(potentialOwner, replicaSets.filter((rs) => rs.status && rs.status.replicas > 0)).reduce((accum, rs) => {
|
|
1002
|
+
return accum.concat(getOwnedResources(rs, pods));
|
|
1003
|
+
}, []);
|
|
1004
|
+
};
|
|
1005
|
+
const getMatchingHpa = (ownerName, ownerKind, hpas) => {
|
|
1006
|
+
return hpas.find((hpa) => {
|
|
1007
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1008
|
+
return ((_c = (_b = (_a = hpa.spec) == null ? void 0 : _a.scaleTargetRef) == null ? void 0 : _b.kind) != null ? _c : "").toLocaleLowerCase("en-US") === ownerKind.toLocaleLowerCase("en-US") && ((_f = (_e = (_d = hpa.spec) == null ? void 0 : _d.scaleTargetRef) == null ? void 0 : _e.name) != null ? _f : "") === (ownerName != null ? ownerName : "unknown-deployment");
|
|
1009
|
+
});
|
|
1010
|
+
};
|
|
1011
|
+
|
|
1012
|
+
const DeploymentSummary = ({
|
|
1013
|
+
deployment,
|
|
1014
|
+
numberOfCurrentPods,
|
|
1015
|
+
numberOfPodsWithErrors,
|
|
1016
|
+
hpa
|
|
1017
|
+
}) => {
|
|
1018
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
1019
|
+
return /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1020
|
+
container: true,
|
|
1021
|
+
direction: "row",
|
|
1022
|
+
justifyContent: "flex-start",
|
|
1023
|
+
alignItems: "center"
|
|
1024
|
+
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1025
|
+
xs: 3,
|
|
1026
|
+
item: true
|
|
1027
|
+
}, /* @__PURE__ */ React__default.createElement(DeploymentDrawer, {
|
|
1028
|
+
deployment
|
|
1029
|
+
})), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1030
|
+
item: true,
|
|
1031
|
+
xs: 1
|
|
1032
|
+
}, /* @__PURE__ */ React__default.createElement(Divider, {
|
|
1033
|
+
style: {height: "5em"},
|
|
1034
|
+
orientation: "vertical"
|
|
1035
|
+
})), hpa && /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1036
|
+
item: true,
|
|
1037
|
+
xs: 3
|
|
1038
|
+
}, /* @__PURE__ */ React__default.createElement(HorizontalPodAutoscalerDrawer, {
|
|
1039
|
+
hpa
|
|
1040
|
+
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1041
|
+
item: true,
|
|
1042
|
+
container: true,
|
|
1043
|
+
direction: "column",
|
|
1044
|
+
justifyContent: "flex-start",
|
|
1045
|
+
alignItems: "flex-start",
|
|
1046
|
+
spacing: 0
|
|
1047
|
+
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1048
|
+
item: true
|
|
1049
|
+
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
1050
|
+
variant: "subtitle2"
|
|
1051
|
+
}, "min replicas ", (_b = (_a = hpa.spec) == null ? void 0 : _a.minReplicas) != null ? _b : "?", " / max replicas", " ", (_d = (_c = hpa.spec) == null ? void 0 : _c.maxReplicas) != null ? _d : "?")), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1052
|
+
item: true
|
|
1053
|
+
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
1054
|
+
variant: "subtitle2"
|
|
1055
|
+
}, "current CPU usage:", " ", (_f = (_e = hpa.status) == null ? void 0 : _e.currentCPUUtilizationPercentage) != null ? _f : "?", "%")), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1056
|
+
item: true
|
|
1057
|
+
}, /* @__PURE__ */ React__default.createElement(Typography, {
|
|
1058
|
+
variant: "subtitle2"
|
|
1059
|
+
}, "target CPU usage:", " ", (_h = (_g = hpa.spec) == null ? void 0 : _g.targetCPUUtilizationPercentage) != null ? _h : "?", "%"))))), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1060
|
+
item: true,
|
|
1061
|
+
container: true,
|
|
1062
|
+
xs: 3,
|
|
1063
|
+
direction: "column",
|
|
1064
|
+
justifyContent: "flex-start",
|
|
1065
|
+
alignItems: "flex-start"
|
|
1066
|
+
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1067
|
+
item: true
|
|
1068
|
+
}, /* @__PURE__ */ React__default.createElement(StatusOK, null, numberOfCurrentPods, " pods")), /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1069
|
+
item: true
|
|
1070
|
+
}, numberOfPodsWithErrors > 0 ? /* @__PURE__ */ React__default.createElement(StatusError, null, numberOfPodsWithErrors, " pod", numberOfPodsWithErrors > 1 ? "s" : "", " with errors") : /* @__PURE__ */ React__default.createElement(StatusOK, null, "No pods with errors"))));
|
|
1071
|
+
};
|
|
1072
|
+
const DeploymentAccordion = ({
|
|
1073
|
+
deployment,
|
|
1074
|
+
ownedPods,
|
|
1075
|
+
matchingHpa
|
|
1076
|
+
}) => {
|
|
1077
|
+
const podNamesWithErrors = useContext(PodNamesWithErrorsContext);
|
|
1078
|
+
const podsWithErrors = ownedPods.filter((p) => {
|
|
1079
|
+
var _a, _b;
|
|
1080
|
+
return podNamesWithErrors.has((_b = (_a = p.metadata) == null ? void 0 : _a.name) != null ? _b : "");
|
|
1081
|
+
});
|
|
1082
|
+
return /* @__PURE__ */ React__default.createElement(Accordion, {
|
|
1083
|
+
TransitionProps: {unmountOnExit: true}
|
|
1084
|
+
}, /* @__PURE__ */ React__default.createElement(AccordionSummary, {
|
|
1085
|
+
expandIcon: /* @__PURE__ */ React__default.createElement(ExpandMoreIcon, null)
|
|
1086
|
+
}, /* @__PURE__ */ React__default.createElement(DeploymentSummary, {
|
|
1087
|
+
deployment,
|
|
1088
|
+
numberOfCurrentPods: ownedPods.length,
|
|
1089
|
+
numberOfPodsWithErrors: podsWithErrors.length,
|
|
1090
|
+
hpa: matchingHpa
|
|
1091
|
+
})), /* @__PURE__ */ React__default.createElement(AccordionDetails, null, /* @__PURE__ */ React__default.createElement(PodsTable, {
|
|
1092
|
+
pods: ownedPods
|
|
1093
|
+
})));
|
|
1094
|
+
};
|
|
1095
|
+
const DeploymentsAccordions = ({}) => {
|
|
1096
|
+
const groupedResponses = useContext(GroupedResponsesContext);
|
|
1097
|
+
return /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1098
|
+
container: true,
|
|
1099
|
+
direction: "column",
|
|
1100
|
+
justifyContent: "flex-start",
|
|
1101
|
+
alignItems: "flex-start"
|
|
1102
|
+
}, groupedResponses.deployments.map((deployment, i) => {
|
|
1103
|
+
var _a;
|
|
1104
|
+
return /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1105
|
+
container: true,
|
|
1106
|
+
item: true,
|
|
1107
|
+
key: i,
|
|
1108
|
+
xs: true
|
|
1109
|
+
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
1110
|
+
item: true,
|
|
1111
|
+
xs: true
|
|
1112
|
+
}, /* @__PURE__ */ React__default.createElement(DeploymentAccordion, {
|
|
1113
|
+
matchingHpa: getMatchingHpa((_a = deployment.metadata) == null ? void 0 : _a.name, "deployment", groupedResponses.horizontalPodAutoscalers),
|
|
1114
|
+
ownedPods: getOwnedPodsThroughReplicaSets(deployment, groupedResponses.replicaSets, groupedResponses.pods),
|
|
1115
|
+
deployment
|
|
1116
|
+
})));
|
|
1117
|
+
}));
|
|
1113
1118
|
};
|
|
1114
1119
|
|
|
1115
1120
|
const IngressDrawer = ({
|
|
@@ -1712,6 +1717,7 @@ const Cluster = ({clusterObjects, podsWithErrors}) => {
|
|
|
1712
1717
|
item: true
|
|
1713
1718
|
}, /* @__PURE__ */ React__default.createElement(ServicesAccordions, null))))))));
|
|
1714
1719
|
};
|
|
1720
|
+
|
|
1715
1721
|
const KubernetesContent = ({entity}) => {
|
|
1716
1722
|
var _a;
|
|
1717
1723
|
const {kubernetesObjects, error} = useKubernetesObjects(entity);
|