From 518808f2546f3abe08e6759a390abeeba2a46492 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 19 May 2022 07:24:04 -0700 Subject: [PATCH] Fix master node classification for kubernetes >1.20 (#5416) --- src/common/k8s-api/__tests__/nodes.test.ts | 51 +++++++++++++++++++ src/common/k8s-api/endpoints/nodes.api.ts | 35 ++++++++++--- src/renderer/components/+nodes/nodes.store.ts | 4 +- 3 files changed, 80 insertions(+), 10 deletions(-) diff --git a/src/common/k8s-api/__tests__/nodes.test.ts b/src/common/k8s-api/__tests__/nodes.test.ts index 4b109a8f96..9589ab7d0d 100644 --- a/src/common/k8s-api/__tests__/nodes.test.ts +++ b/src/common/k8s-api/__tests__/nodes.test.ts @@ -9,6 +9,57 @@ import { Node } from "../endpoints"; * Licensed under MIT License. See LICENSE in root directory for more information. */ describe("Nodes tests", () => { + describe("isMasterNode()", () => { + it("given a master node labelled before kubernetes 1.20, should return true", () => { + const node = new Node({ + apiVersion: "foo", + kind: "Node", + metadata: { + name: "bar", + resourceVersion: "1", + uid: "bat", + labels: { + "node-role.kubernetes.io/master": "NoSchedule", + }, + }, + }); + + expect(node.isMasterNode()).toBe(true); + }); + + it("given a master node labelled after kubernetes 1.20, should return true", () => { + const node = new Node({ + apiVersion: "foo", + kind: "Node", + metadata: { + name: "bar", + resourceVersion: "1", + uid: "bat", + labels: { + "node-role.kubernetes.io/control-plane": "NoSchedule", + }, + }, + }); + + expect(node.isMasterNode()).toBe(true); + }); + + it("given a non master node, should return false", () => { + const node = new Node({ + apiVersion: "foo", + kind: "Node", + metadata: { + name: "bar", + resourceVersion: "1", + uid: "bat", + labels: {}, + }, + }); + + expect(node.isMasterNode()).toBe(false); + }); + }); + describe("getRoleLabels()", () => { it("should return empty string if labels is not present", () => { const node = new Node({ diff --git a/src/common/k8s-api/endpoints/nodes.api.ts b/src/common/k8s-api/endpoints/nodes.api.ts index 62edc090e4..66a3ce9d26 100644 --- a/src/common/k8s-api/endpoints/nodes.api.ts +++ b/src/common/k8s-api/endpoints/nodes.api.ts @@ -4,7 +4,7 @@ */ import { KubeObject } from "../kube-object"; -import { autoBind, cpuUnitsToNumber, iter, unitsToBytes } from "../../../renderer/utils"; +import { autoBind, cpuUnitsToNumber, isObject, iter, unitsToBytes } from "../../../renderer/utils"; import type { IMetrics } from "./metrics.api"; import { metricsApi } from "./metrics.api"; import { KubeApi } from "../kube-api"; @@ -141,6 +141,17 @@ function* getTrueConditionTypes(conditions: IterableIterator | It } } +/** + * These role label prefixs are the ones that are for master nodes + * + * The `master` label has been deprecated in Kubernetes 1.20, and will be removed in 1.25 so we + * have to also use the newer `control-plane` label + */ +const masterNodeLabels = [ + "master", + "control-plane", +]; + /** * This regex is used in the `getRoleLabels()` method bellow, but placed here * as factoring out regexes is best practice. @@ -172,15 +183,19 @@ export class Node extends KubeObject { return this.spec.taints || []; } - getRoleLabels(): string { + isMasterNode(): boolean { + return this.getRoleLabelItems() + .some(roleLabel => masterNodeLabels.includes(roleLabel)); + } + + getRoleLabelItems(): string[] { const { labels } = this.metadata; - - if (!labels || typeof labels !== "object") { - return ""; - } - const roleLabels: string[] = []; + if (!isObject(labels)) { + return roleLabels; + } + for (const labelKey of Object.keys(labels)) { const match = nodeRoleLabelKeyMatcher.exec(labelKey); @@ -197,7 +212,11 @@ export class Node extends KubeObject { roleLabels.push(labels["node.kubernetes.io/role"]); } - return roleLabels.join(", "); + return roleLabels; + } + + getRoleLabels(): string { + return this.getRoleLabelItems().join(", "); } getCpuCapacity() { diff --git a/src/renderer/components/+nodes/nodes.store.ts b/src/renderer/components/+nodes/nodes.store.ts index f80b3fcddd..fc0f25bdca 100644 --- a/src/renderer/components/+nodes/nodes.store.ts +++ b/src/renderer/components/+nodes/nodes.store.ts @@ -22,11 +22,11 @@ export class NodesStore extends KubeObjectStore { } @computed get masterNodes() { - return this.items.filter(node => node.getRoleLabels().includes("master")); + return this.items.filter(node => node.isMasterNode()); } @computed get workerNodes() { - return this.items.filter(node => !node.getRoleLabels().includes("master")); + return this.items.filter(node => !node.isMasterNode()); } getWarningsCount(): number {