From 10687447cb2d11aab44c5a8845f78285e4190ef8 Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Wed, 23 Aug 2017 00:48:59 -0400 Subject: [PATCH] Print multiple node roles, remove kubeadm-specific annotation from kubectl --- pkg/printers/internalversion/describe.go | 6 +- pkg/printers/internalversion/printers.go | 54 +++++++------- pkg/printers/internalversion/printers_test.go | 73 ++++++++++++------- 3 files changed, 77 insertions(+), 56 deletions(-) diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index 00e732dd4a2..8de1e173a7c 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -2436,7 +2436,11 @@ func describeNode(node *api.Node, nodeNonTerminatedPodsList *api.PodList, events return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) w.Write(LEVEL_0, "Name:\t%s\n", node.Name) - w.Write(LEVEL_0, "Role:\t%s\n", findNodeRole(node)) + if roles := findNodeRoles(node); len(roles) > 0 { + w.Write(LEVEL_0, "Roles:\t%s\n", strings.Join(roles, ",")) + } else { + w.Write(LEVEL_0, "Roles:\t%s\n", "") + } printLabelsMultiline(w, "Labels", node.Labels) printAnnotationsMultiline(w, "Annotations", node.Annotations) printNodeTaintsMultiline(w, "Taints", node.Spec.Taints) diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index e763d9ea8e2..221e9223d7c 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -62,16 +62,12 @@ import ( const ( loadBalancerWidth = 16 - // LabelNodeRoleMaster specifies that a node is a master + // labelNodeRolePrefix is a label prefix for node roles // It's copied over to here until it's merged in core: https://github.com/kubernetes/kubernetes/pull/39112 - LabelNodeRoleMaster = "node-role.kubernetes.io/master" + labelNodeRolePrefix = "node-role.kubernetes.io/" - // NodeLabelRole specifies the role of a node - NodeLabelRole = "kubernetes.io/role" - - // NodeLabelKubeadmAlphaRole is a label that kubeadm applies to a Node as a hint that it has a particular purpose. - // Use of NodeLabelRole is preferred. - NodeLabelKubeadmAlphaRole = "kubeadm.alpha.kubernetes.io/role" + // nodeLabelRole specifies the role of a node + nodeLabelRole = "kubernetes.io/role" ) // AddHandlers adds print handlers for default Kubernetes types dealing with internal versions. @@ -221,6 +217,7 @@ func AddHandlers(h printers.PrintHandler) { nodeColumnDefinitions := []metav1alpha1.TableColumnDefinition{ {Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]}, {Name: "Status", Type: "string", Description: "The status of the node"}, + {Name: "Roles", Type: "string", Description: "The roles of the node"}, {Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]}, {Name: "Version", Type: "string", Description: apiv1.NodeSystemInfo{}.SwaggerDoc()["kubeletVersion"]}, {Name: "External-IP", Type: "string", Priority: 1, Description: apiv1.NodeStatus{}.SwaggerDoc()["addresses"]}, @@ -1167,12 +1164,13 @@ func printNode(obj *api.Node, options printers.PrintOptions) ([]metav1alpha1.Tab if obj.Spec.Unschedulable { status = append(status, "SchedulingDisabled") } - role := findNodeRole(obj) - if role != "" { - status = append(status, role) + + roles := strings.Join(findNodeRoles(obj), ",") + if len(roles) == 0 { + roles = "" } - row.Cells = append(row.Cells, obj.Name, strings.Join(status, ","), translateTimestamp(obj.CreationTimestamp), obj.Status.NodeInfo.KubeletVersion) + row.Cells = append(row.Cells, obj.Name, strings.Join(status, ","), roles, translateTimestamp(obj.CreationTimestamp), obj.Status.NodeInfo.KubeletVersion) if options.Wide { osImage, kernelVersion, crVersion := obj.Status.NodeInfo.OSImage, obj.Status.NodeInfo.KernelVersion, obj.Status.NodeInfo.ContainerRuntimeVersion if osImage == "" { @@ -1201,22 +1199,24 @@ func getNodeExternalIP(node *api.Node) string { return "" } -// findNodeRole returns the role of a given node, or "" if none found. -// The role is determined by looking in order for: -// * a node-role.kubernetes.io/master label -// * a kubernetes.io/role label -// * a kubeadm.alpha.kubernetes.io/role label -func findNodeRole(node *api.Node) string { - if _, ok := node.Labels[LabelNodeRoleMaster]; ok { - return "Master" +// findNodeRoles returns the roles of a given node. +// The roles are determined by looking for: +// * a node-role.kubernetes.io/="" label +// * a kubernetes.io/role="" label +func findNodeRoles(node *api.Node) []string { + roles := sets.NewString() + for k, v := range node.Labels { + switch { + case strings.HasPrefix(k, labelNodeRolePrefix): + if role := strings.TrimPrefix(k, labelNodeRolePrefix); len(role) > 0 { + roles.Insert(role) + } + + case k == nodeLabelRole && v != "": + roles.Insert(v) + } } - if role := node.Labels[NodeLabelRole]; role != "" { - return strings.Title(role) - } - if role := node.Labels[NodeLabelKubeadmAlphaRole]; role != "" { - return strings.Title(role) - } - return "" + return roles.List() } func printNodeList(list *api.NodeList, options printers.PrintOptions) ([]metav1alpha1.TableRow, error) { diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index b3909b0a2ed..7407ef19609 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -825,34 +825,6 @@ func TestPrintNodeStatus(t *testing.T) { }, status: "Unknown,SchedulingDisabled", }, - { - node: api.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo10", - Labels: map[string]string{"node-role.kubernetes.io/master": "", "kubernetes.io/role": "node", "kubeadm.alpha.kubernetes.io/role": "node"}, - }, - }, - status: "Unknown,Master", - }, - { - node: api.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo11", - Labels: map[string]string{"kubernetes.io/role": "node", "kubeadm.alpha.kubernetes.io/role": "node"}, - }, - }, - status: "Unknown,Node", - }, - { - node: api.Node{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo12", - Labels: map[string]string{"kubeadm.alpha.kubernetes.io/role": "node"}, - }, - Status: api.NodeStatus{Conditions: []api.NodeCondition{{Type: api.NodeReady, Status: api.ConditionTrue}}}, - }, - status: "Ready,Node", - }, } for _, test := range table { @@ -867,6 +839,51 @@ func TestPrintNodeStatus(t *testing.T) { } } +func TestPrintNodeRole(t *testing.T) { + printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{}) + AddHandlers(printer) + table := []struct { + node api.Node + expected string + }{ + { + node: api.Node{ + ObjectMeta: metav1.ObjectMeta{Name: "foo9"}, + }, + expected: "", + }, + { + node: api.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo10", + Labels: map[string]string{"node-role.kubernetes.io/master": "", "node-role.kubernetes.io/proxy": "", "kubernetes.io/role": "node"}, + }, + }, + expected: "master,node,proxy", + }, + { + node: api.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo11", + Labels: map[string]string{"kubernetes.io/role": "node"}, + }, + }, + expected: "node", + }, + } + + for _, test := range table { + buffer := &bytes.Buffer{} + err := printer.PrintObj(&test.node, buffer) + if err != nil { + t.Fatalf("An error occurred printing Node: %#v", err) + } + if !contains(strings.Fields(buffer.String()), test.expected) { + t.Fatalf("Expect printing node %s with role %#v, got: %#v", test.node.Name, test.expected, buffer.String()) + } + } +} + func TestPrintNodeOSImage(t *testing.T) { printer := printers.NewHumanReadablePrinter(nil, nil, printers.PrintOptions{ ColumnLabels: []string{},