Print multiple node roles, remove kubeadm-specific annotation from kubectl
This commit is contained in:
		| @@ -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", "<none>") | ||||
| 		} | ||||
| 		printLabelsMultiline(w, "Labels", node.Labels) | ||||
| 		printAnnotationsMultiline(w, "Annotations", node.Annotations) | ||||
| 		printNodeTaintsMultiline(w, "Taints", node.Spec.Taints) | ||||
|   | ||||
| @@ -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 = "<none>" | ||||
| 	} | ||||
|  | ||||
| 	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 "<none>" | ||||
| } | ||||
|  | ||||
| // 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/<role>="" label | ||||
| // * a kubernetes.io/role="<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) { | ||||
|   | ||||
| @@ -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: "<none>", | ||||
| 		}, | ||||
| 		{ | ||||
| 			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{}, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jordan Liggitt
					Jordan Liggitt