- Desired:
- ${entity.attributes.status.replicas ??
- entity.attributes.status.desired_number_scheduled ??
- 0}
-
-
- Ready:
- ${entity.attributes.status.ready_replicas ??
- entity.attributes.status.number_ready ??
- 0}
-
+
Updated:
${entity.attributes.status.updated_replicas ??
@@ -246,12 +242,12 @@ export class ComponentDetailsCard extends LitElement {
}
renderNode(entity) {
- if (!entity.attributes.spec.node_name) return;
+ if (!getNodeName(entity)) return;
return html`
Node |
- ${entity.attributes.spec.node_name}
+ ${getNodeName(entity)}
|
`;
diff --git a/frontend/src/helpers.js b/frontend/src/helpers.js
index 35b4b7e..f9c7bca 100644
--- a/frontend/src/helpers.js
+++ b/frontend/src/helpers.js
@@ -1,9 +1,12 @@
import { html } from "lit";
-import { state } from "lit-element";
-const stateError = "error";
-const stateWarning = "warning";
-const stateSuccess = "success";
+export const stateError = "error";
+export const stateWarning = "warning";
+export const stateSuccess = "success";
+
+export function getState(entity_row) {
+ return entity_row.state;
+}
export function getName(entity_row) {
return entity_row.attributes.metadata.name;
@@ -13,27 +16,49 @@ export function getNamespace(entity_row) {
return entity_row.attributes.metadata.namespace;
}
-export function getConditions(entity_row) {
- return entity_row.attributes.status.conditions;
+export function getConditions(entity_row, filter) {
+ let conditions = entity_row.attributes.status.conditions;
+
+ if (filter) {
+ conditions = conditions.filter((condition) => {
+ let condition_filter = filter[condition.type];
+ let condition_state = getConditionStateMapper(condition);
+ // prettier-ignore
+ return (!condition_filter) ||
+ (condition_filter == stateSuccess) ||
+ (condition_filter == stateWarning && (condition_state == stateWarning || condition_state == stateError)) ||
+ (condition_filter == stateError && condition_state == stateError)
+ });
+ }
+
+ return conditions;
}
export function getNodeSchedulable(entity_row) {
return !entity_row.attributes.spec.unschedulable;
}
-export function getNodeSchedulableIcon(value) {
- if (value) {
- return html`
`;
- } else {
- return html`
`;
- }
+export function getCreated(entity_row) {
+ return new Date(entity_row.attributes.metadata.creation_timestamp);
}
-export function getNodeSchedulableStateClass(entity_row) {
+export function getAge(entity_row) {
+ return Date.now() - getCreated(entity_row);
+}
+
+export function getAgeStr(entity_row) {
+ var ms = getAge(entity_row);
+ var d = Math.floor(ms / 86400000);
+ var h = Math.floor((ms / 3600000) % 24);
+
+ return `${d}d${h}h`;
+}
+
+export function getNodeSchedulableIcon(entity_row) {
if (getNodeSchedulable(entity_row)) {
- return stateSuccess;
+ return html`
`;
} else {
- return stateError;
+ return html`
`;
}
}
@@ -83,10 +108,15 @@ export function getConditionStateMapper(condition) {
},
};
- return conditionStateMap[condition.type][condition.reason] ?? conditionStateMap[condition.type][condition.status];
+ return (
+ conditionStateMap[condition.type][condition.reason] ??
+ conditionStateMap[condition.type][condition.status]
+ );
}
-export function getConditionsAsSpans(conditions) {
+export function getConditionsAsSpans(entity_row) {
+ let conditions = getConditions(entity_row, this);
+
return html`
${conditions.map((condition) => {
return html`
@@ -97,3 +127,39 @@ export function getConditionsAsSpans(conditions) {
})}
`;
}
+
+export function getConditionsStrings(entity_row) {
+ let conditions = getConditions(entity_row, this);
+
+ return `
+ ${conditions.map((condition) => {
+ return `
+ ${condition.reason ? condition.reason : condition.type}
+ `;
+ })}
+ `;
+}
+
+export function getNodeName(entity_row) {
+ return entity_row.attributes.spec.node_name;
+}
+
+export function getDesiredReplicas(entity_row) {
+ return (
+ entity_row.attributes.status.replicas ??
+ entity_row.attributes.status.desired_number_scheduled ??
+ 0
+ );
+}
+
+export function getReadyReplicas(entity_row) {
+ return (
+ entity_row.attributes.status.ready_replicas ??
+ entity_row.attributes.status.number_ready ??
+ 0
+ );
+}
+
+export function getReplicaStr(entity_row) {
+ return `${getReadyReplicas(entity_row)}/${getDesiredReplicas(entity_row)}`;
+}
diff --git a/frontend/src/panel.js b/frontend/src/panel.js
index c843fae..e035b21 100644
--- a/frontend/src/panel.js
+++ b/frontend/src/panel.js
@@ -6,15 +6,24 @@ import "./table-card.js";
import "./component-details-card.js";
import "./namespace-selector.js";
import {
+ stateSuccess,
+ stateWarning,
+ stateError,
getName,
getNamespace,
- getConditions,
getConditionsAsSpans,
+ getConditionsStrings,
getNodeSchedulable,
getNodeSchedulableIcon,
- getNodeSchedulableStateClass,
+ getAge,
+ getAgeStr,
+ getState,
+ getNodeName,
+ getReplicaStr,
} from "./helpers.js";
+const componentDetailsCardName = "custom:k8s-component-details";
+
class KubernetesPanel extends LitElement {
constructor() {
super();
@@ -43,77 +52,130 @@ class KubernetesPanel extends LitElement {
switch (this._page) {
case "Node":
+ var conditionFilter = {
+ NetworkUnavailable: stateWarning,
+ MemoryPressure: stateWarning,
+ DiskPressure: stateWarning,
+ PIDPressure: stateWarning,
+ };
+
return {
popUpCard: {
- type: "custom:k8s-component-details",
+ type: componentDetailsCardName,
},
columns: {
Name: {
- function: getName,
+ value: getName,
+ sort_value: getName,
},
Schedulable: {
- function: getNodeSchedulable,
- transformation: getNodeSchedulableIcon,
- state_function: getNodeSchedulableStateClass,
+ value: getNodeSchedulableIcon,
+ sort_value: getNodeSchedulable,
+ },
+ Age: {
+ value: getAgeStr,
+ sort_value: getAge,
},
Conditions: {
- function: getConditions,
- transformation: getConditionsAsSpans,
+ value: getConditionsAsSpans.bind(conditionFilter),
+ sort_value: getConditionsStrings.bind(conditionFilter),
},
},
filter_functions: [filterByPage],
};
case "Deployment":
+ var conditionFilter = {
+ Progressing: stateWarning,
+ };
+
return {
popUpCard: {
- type: "custom:k8s-component-details",
+ type: componentDetailsCardName,
},
columns: {
Name: {
- function: getName,
+ value: getName,
+ sort_value: getName,
},
Namespace: {
- function: getNamespace,
+ value: getNamespace,
+ sort_value: getNamespace,
+ },
+ Replicas: {
+ value: getReplicaStr,
+ sort_value: getReplicaStr,
+ },
+ Age: {
+ value: getAgeStr,
+ sort_value: getAge,
+ },
+ Conditions: {
+ value: getConditionsAsSpans.bind(conditionFilter),
+ sort_value: getConditionsStrings.bind(conditionFilter),
},
- State: { function: "return entity_row.state" },
},
filter_functions: [filterByPage, filterByNamespace],
};
case "DaemonSet":
return {
popUpCard: {
- type: "custom:k8s-component-details",
+ type: componentDetailsCardName,
},
columns: {
Name: {
- function: getName,
+ value: getName,
+ sort_value: getName,
},
Namespace: {
- function: getNamespace,
+ value: getNamespace,
+ sort_value: getNamespace,
+ },
+ Replicas: {
+ value: getReplicaStr,
+ sort_value: getReplicaStr,
+ },
+ Age: {
+ value: getAgeStr,
+ sort_value: getAge,
},
- State: { function: "return entity_row.state" },
},
filter_functions: [filterByPage, filterByNamespace],
};
case "Pod":
+ var conditionFilter = {
+ Initialized: stateWarning,
+ ContainersReady: stateWarning,
+ PodScheduled: stateWarning,
+ };
+
return {
popUpCard: {
- type: "custom:k8s-component-details",
+ type: componentDetailsCardName,
},
columns: {
Name: {
- function: getName,
+ value: getName,
+ sort_value: getName,
},
Namespace: {
- function: getNamespace,
+ value: getNamespace,
+ sort_value: getNamespace,
},
Node: {
- function: "return entity_row.attributes.spec.node_name",
+ value: getNodeName,
+ sort_value: getNodeName,
+ },
+ State: {
+ value: getState,
+ sort_value: getState,
+ },
+ Age: {
+ value: getAgeStr,
+ sort_value: getAge,
},
- State: { function: "return entity_row.state" },
Conditions: {
- function: getConditions,
- transformation: getConditionsAsSpans,
+ value: getConditionsAsSpans.bind(conditionFilter),
+ sort_value: getConditionsStrings.bind(conditionFilter),
},
},
filter_functions: [filterByPage, filterByNamespace],
diff --git a/frontend/src/table-card.js b/frontend/src/table-card.js
index e96a3e9..1548ad9 100644
--- a/frontend/src/table-card.js
+++ b/frontend/src/table-card.js
@@ -76,11 +76,10 @@ export class TableCard extends LitElement {
_entityID: state.entity_id,
};
for (const [header, column] of Object.entries(this.config.columns)) {
- var func = this.getAsFunction(column.function, "", "entity_row");
obj[header] = {
- value: this.getAsFunction(column.function, "", "entity_row")(state),
- state: this.getAsFunction(
- column.state_function,
+ value: this.getAsFunction(column.value, "", "entity_row")(state),
+ sortValue: this.getAsFunction(
+ column.sort_value,
"",
"entity_row"
)(state),
@@ -99,8 +98,8 @@ export class TableCard extends LitElement {
}
data.sort((a, b) => {
- var valA = this.sort.by in a ? a[this.sort.by].value : 0;
- var valB = this.sort.by in b ? b[this.sort.by].value : 0;
+ var valA = this.sort.by in a ? a[this.sort.by].sortValue : 0;
+ var valB = this.sort.by in b ? b[this.sort.by].sortValue : 0;
if (valA < valB) {
return this.sort.DESC ? 1 : -1;
}
@@ -162,13 +161,7 @@ export class TableCard extends LitElement {
>
${Object.keys(this.config.columns).map((header) => {
return html`
-
+
`;
})}