Merge pull request #95269 from SataQiu/kubelet-20201003
Fix panic when kubelet register if a node object already exists with no Status.Capacity or Status.Allocatable
This commit is contained in:
		| @@ -127,7 +127,7 @@ func (kl *Kubelet) tryRegisterWithAPIServer(node *v1.Node) bool { | ||||
|  | ||||
| // reconcileHugePageResource will update huge page capacity for each page size and remove huge page sizes no longer supported | ||||
| func (kl *Kubelet) reconcileHugePageResource(initialNode, existingNode *v1.Node) bool { | ||||
| 	requiresUpdate := false | ||||
| 	requiresUpdate := updateDefaultResources(initialNode, existingNode) | ||||
| 	supportedHugePageResources := sets.String{} | ||||
|  | ||||
| 	for resourceName := range initialNode.Status.Capacity { | ||||
| @@ -174,7 +174,7 @@ func (kl *Kubelet) reconcileHugePageResource(initialNode, existingNode *v1.Node) | ||||
|  | ||||
| // Zeros out extended resource capacity during reconciliation. | ||||
| func (kl *Kubelet) reconcileExtendedResource(initialNode, node *v1.Node) bool { | ||||
| 	requiresUpdate := false | ||||
| 	requiresUpdate := updateDefaultResources(initialNode, node) | ||||
| 	// Check with the device manager to see if node has been recreated, in which case extended resources should be zeroed until they are available | ||||
| 	if kl.containerManager.ShouldResetExtendedResourceCapacity() { | ||||
| 		for k := range node.Status.Capacity { | ||||
| @@ -189,6 +189,29 @@ func (kl *Kubelet) reconcileExtendedResource(initialNode, node *v1.Node) bool { | ||||
| 	return requiresUpdate | ||||
| } | ||||
|  | ||||
| // updateDefaultResources will set the default resources on the existing node according to the initial node | ||||
| func updateDefaultResources(initialNode, existingNode *v1.Node) bool { | ||||
| 	requiresUpdate := false | ||||
| 	if existingNode.Status.Capacity == nil { | ||||
| 		if initialNode.Status.Capacity != nil { | ||||
| 			existingNode.Status.Capacity = initialNode.Status.Capacity.DeepCopy() | ||||
| 			requiresUpdate = true | ||||
| 		} else { | ||||
| 			existingNode.Status.Capacity = make(map[v1.ResourceName]resource.Quantity) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if existingNode.Status.Allocatable == nil { | ||||
| 		if initialNode.Status.Allocatable != nil { | ||||
| 			existingNode.Status.Allocatable = initialNode.Status.Allocatable.DeepCopy() | ||||
| 			requiresUpdate = true | ||||
| 		} else { | ||||
| 			existingNode.Status.Allocatable = make(map[v1.ResourceName]resource.Quantity) | ||||
| 		} | ||||
| 	} | ||||
| 	return requiresUpdate | ||||
| } | ||||
|  | ||||
| // updateDefaultLabels will set the default labels on the node | ||||
| func (kl *Kubelet) updateDefaultLabels(initialNode, existingNode *v1.Node) bool { | ||||
| 	defaultLabels := []string{ | ||||
|   | ||||
| @@ -1147,6 +1147,13 @@ func TestRegisterWithApiServer(t *testing.T) { | ||||
| 		}, nil | ||||
| 	}) | ||||
|  | ||||
| 	kubeClient.AddReactor("patch", "nodes", func(action core.Action) (bool, runtime.Object, error) { | ||||
| 		if action.GetSubresource() == "status" { | ||||
| 			return true, nil, nil | ||||
| 		} | ||||
| 		return notImplemented(action) | ||||
| 	}) | ||||
|  | ||||
| 	addNotImplatedReaction(kubeClient) | ||||
|  | ||||
| 	machineInfo := &cadvisorapi.MachineInfo{ | ||||
| @@ -1705,6 +1712,216 @@ func TestUpdateDefaultLabels(t *testing.T) { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestUpdateDefaultResources(t *testing.T) { | ||||
| 	cases := []struct { | ||||
| 		name         string | ||||
| 		initialNode  *v1.Node | ||||
| 		existingNode *v1.Node | ||||
| 		expectedNode *v1.Node | ||||
| 		needsUpdate  bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			name: "no update needed when capacity and allocatable of the existing node are not nil", | ||||
| 			initialNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			existingNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			needsUpdate: false, | ||||
| 		}, { | ||||
| 			name:        "no update needed when capacity and allocatable of the initial node are nil", | ||||
| 			initialNode: &v1.Node{}, | ||||
| 			existingNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			needsUpdate: false, | ||||
| 		}, { | ||||
| 			name: "update needed when capacity and allocatable of the existing node are nil and capacity and allocatable of the initial node are not nil", | ||||
| 			initialNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			existingNode: &v1.Node{}, | ||||
| 			expectedNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			needsUpdate: true, | ||||
| 		}, { | ||||
| 			name: "update needed when capacity of the existing node is nil and capacity of the initial node is not nil", | ||||
| 			initialNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			existingNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			needsUpdate: true, | ||||
| 		}, { | ||||
| 			name: "update needed when allocatable of the existing node is nil and allocatable of the initial node is not nil", | ||||
| 			initialNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			existingNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			needsUpdate: true, | ||||
| 		}, { | ||||
| 			name:         "no update needed but capacity and allocatable of existing node should be initialized", | ||||
| 			initialNode:  &v1.Node{}, | ||||
| 			existingNode: &v1.Node{}, | ||||
| 			expectedNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity:    v1.ResourceList{}, | ||||
| 					Allocatable: v1.ResourceList{}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			needsUpdate: false, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range cases { | ||||
| 		t.Run(tc.name, func(T *testing.T) { | ||||
| 			needsUpdate := updateDefaultResources(tc.initialNode, tc.existingNode) | ||||
| 			assert.Equal(t, tc.needsUpdate, needsUpdate, tc.name) | ||||
| 			assert.Equal(t, tc.expectedNode, tc.existingNode, tc.name) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestReconcileHugePageResource(t *testing.T) { | ||||
| 	testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) | ||||
| 	hugePageResourceName64Ki := v1.ResourceName("hugepages-64Ki") | ||||
| @@ -1939,6 +2156,49 @@ func TestReconcileHugePageResource(t *testing.T) { | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, { | ||||
| 			name:        "not panic when capacity or allocatable of existing node is nil", | ||||
| 			testKubelet: testKubelet, | ||||
| 			needsUpdate: true, | ||||
| 			initialNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						hugePageResourceName2Mi:     resource.MustParse("100Mi"), | ||||
| 						hugePageResourceName64Ki:    *resource.NewQuantity(0, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						hugePageResourceName2Mi:     resource.MustParse("100Mi"), | ||||
| 						hugePageResourceName64Ki:    *resource.NewQuantity(0, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			existingNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{}, | ||||
| 			}, | ||||
| 			expectedNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						hugePageResourceName2Mi:     resource.MustParse("100Mi"), | ||||
| 						hugePageResourceName64Ki:    *resource.NewQuantity(0, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						hugePageResourceName2Mi:     resource.MustParse("100Mi"), | ||||
| 						hugePageResourceName64Ki:    *resource.NewQuantity(0, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| @@ -1966,6 +2226,7 @@ func TestReconcileExtendedResource(t *testing.T) { | ||||
| 	cases := []struct { | ||||
| 		name         string | ||||
| 		testKubelet  *TestKubelet | ||||
| 		initialNode  *v1.Node | ||||
| 		existingNode *v1.Node | ||||
| 		expectedNode *v1.Node | ||||
| 		needsUpdate  bool | ||||
| @@ -1973,7 +2234,7 @@ func TestReconcileExtendedResource(t *testing.T) { | ||||
| 		{ | ||||
| 			name:        "no update needed without extended resource", | ||||
| 			testKubelet: testKubelet, | ||||
| 			existingNode: &v1.Node{ | ||||
| 			initialNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| @@ -1987,25 +2248,6 @@ func TestReconcileExtendedResource(t *testing.T) { | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			needsUpdate: false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:        "extended resource capacity is not zeroed due to presence of checkpoint file", | ||||
| 			testKubelet: testKubelet, | ||||
| 			existingNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| @@ -2039,6 +2281,24 @@ func TestReconcileExtendedResource(t *testing.T) { | ||||
| 		{ | ||||
| 			name:        "extended resource capacity is zeroed", | ||||
| 			testKubelet: testKubeletNoReset, | ||||
| 			initialNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						extendedResourceName1:       *resource.NewQuantity(int64(2), resource.DecimalSI), | ||||
| 						extendedResourceName2:       *resource.NewQuantity(int64(10), resource.DecimalSI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						extendedResourceName1:       *resource.NewQuantity(int64(2), resource.DecimalSI), | ||||
| 						extendedResourceName2:       *resource.NewQuantity(int64(10), resource.DecimalSI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			existingNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| @@ -2077,14 +2337,65 @@ func TestReconcileExtendedResource(t *testing.T) { | ||||
| 			}, | ||||
| 			needsUpdate: true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			name:        "not panic when allocatable of existing node is nil", | ||||
| 			testKubelet: testKubelet, | ||||
| 			initialNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						extendedResourceName1:       *resource.NewQuantity(int64(2), resource.DecimalSI), | ||||
| 						extendedResourceName2:       *resource.NewQuantity(int64(10), resource.DecimalSI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						extendedResourceName1:       *resource.NewQuantity(int64(2), resource.DecimalSI), | ||||
| 						extendedResourceName2:       *resource.NewQuantity(int64(10), resource.DecimalSI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			existingNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						extendedResourceName1:       *resource.NewQuantity(int64(2), resource.DecimalSI), | ||||
| 						extendedResourceName2:       *resource.NewQuantity(int64(10), resource.DecimalSI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			expectedNode: &v1.Node{ | ||||
| 				Status: v1.NodeStatus{ | ||||
| 					Capacity: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						extendedResourceName1:       *resource.NewQuantity(int64(0), resource.DecimalSI), | ||||
| 						extendedResourceName2:       *resource.NewQuantity(int64(0), resource.DecimalSI), | ||||
| 					}, | ||||
| 					Allocatable: v1.ResourceList{ | ||||
| 						v1.ResourceCPU:              *resource.NewMilliQuantity(2000, resource.DecimalSI), | ||||
| 						v1.ResourceMemory:           *resource.NewQuantity(10e9, resource.BinarySI), | ||||
| 						v1.ResourceEphemeralStorage: *resource.NewQuantity(5000, resource.BinarySI), | ||||
| 						extendedResourceName1:       *resource.NewQuantity(int64(0), resource.DecimalSI), | ||||
| 						extendedResourceName2:       *resource.NewQuantity(int64(0), resource.DecimalSI), | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			needsUpdate: true, | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	for _, tc := range cases { | ||||
| 		defer testKubelet.Cleanup() | ||||
| 		kubelet := testKubelet.kubelet | ||||
| 		initialNode := &v1.Node{} | ||||
|  | ||||
| 		needsUpdate := kubelet.reconcileExtendedResource(initialNode, tc.existingNode) | ||||
| 		needsUpdate := kubelet.reconcileExtendedResource(tc.initialNode, tc.existingNode) | ||||
| 		assert.Equal(t, tc.needsUpdate, needsUpdate, tc.name) | ||||
| 		assert.Equal(t, tc.expectedNode, tc.existingNode, tc.name) | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Kubernetes Prow Robot
					Kubernetes Prow Robot