Repository: kubernetes/kubernetes
File: test/e2e/framework/node/resource.go (Go)

Code before:
	// Simple lookup for nonblocking taints based on comma-delimited list.
	nonblockingTaintsMap := map[string]struct{}{}
	for _, t := range strings.Split(nonblockingTaints, ",") {
		if strings.TrimSpace(t) != "" {
			nonblockingTaintsMap[strings.TrimSpace(t)] = struct{}{}
		}
	}

	for _, taint := range node.Spec.Taints {
		if _, hasNonblockingTaint := nonblockingTaintsMap[taint.Key]; hasNonblockingTaint {
			return true
		}
	}

	return false
}

// GetNodeAllocatableAndAvailableValues with resourceName set to v1.ResourceCPU ( or set to v1.ResourceMemory ) returns
//   - as a first return value, the allocatable portion of a node's total "CPU" ( or "Memory" ) capacity that's available for pods to use,
//     calculated by subtracting "CPU" ( or "Memory") resources reserved for node's operating system, Kubelet and other
//     system daemons from the node's total "CPU" resource in MilliValue ( or "Memory" resource in Value ) upon success, 0 upon failure.
//   - as a second return value, the available portion of a node's allocatable "CPU" capacity, calculated by subtracting "CPU"
//     resources ( or "Memory" resource ) reserved for node's pods from the node's allocatable "CPU" resource in MilliValue
//     ( or "Memory" resource in Value ) upon success, 0 upon failure.
//   - as a third return value, nil upon success or an error upon failure.
func GetNodeAllocatableAndAvailableValues(ctx context.Context, c clientset.Interface, n *v1.Node, resourceName v1.ResourceName) (int64, int64, error) {
	var nodeAllocatable int64
	switch resourceName {
	case v1.ResourceCPU:
		nodeAllocatable = n.Status.Allocatable.Cpu().MilliValue()
	case v1.ResourceMemory:
		nodeAllocatable = n.Status.Allocatable.Memory().Value()
	default:
		return 0, 0, fmt.Errorf("unexpected resource type %q; expected either 'CPU' or 'Memory'", resourceName)
	}

	if n.Status.Allocatable == nil {
		return 0, 0, fmt.Errorf("unexpected empty value of allocatable")
	}

	// Exclude pods that are in the Succeeded or Failed states
	selector := fmt.Sprintf("spec.nodeName=%s,status.phase!=%v,status.phase!=%v", n.Name, v1.PodSucceeded, v1.PodFailed)
	listOptions := metav1.ListOptions{FieldSelector: selector}
	podList, err := c.CoreV1().Pods(metav1.NamespaceAll).List(ctx, listOptions)
	if err != nil {
		return 0, 0, fmt.Errorf("error getting list of pods: %w", err)
	}

	podAllocated := int64(0)
	for _, pod := range podList.Items {
		podRequest := resourceapi.GetResourceRequest(&pod, resourceName)

Review comment (suggestion):
I'm still not sure why `int64` is used as return type instead of `resource.Quantity`.


Code after:
	// Simple lookup for nonblocking taints based on comma-delimited list.
	nonblockingTaintsMap := map[string]struct{}{}
	for _, t := range strings.Split(nonblockingTaints, ",") {
		if strings.TrimSpace(t) != "" {
			nonblockingTaintsMap[strings.TrimSpace(t)] = struct{}{}
		}
	}

	for _, taint := range node.Spec.Taints {
		if _, hasNonblockingTaint := nonblockingTaintsMap[taint.Key]; hasNonblockingTaint {
			return true
		}
	}

	return false
}

// GetNodeAllocatableAndAvailableQuantities with resourceName set to v1.ResourceCPU ( or set to v1.ResourceMemory ) returns
//   - the first return value, upon success is the allocatable portion of a node's total "CPU" ( or "Memory" ) capacity that's available for pods to use,
//     calculated by subtracting "CPU" ( or "Memory") resources reserved for node's operating system, Kubelet and other
//     system daemons from the node's total "CPU" ( or "Memory" ) resource, upon failure is empty.
//   - the second return value, upon success is the available portion of a node's allocatable "CPU" capacity, calculated by subtracting "CPU"
//     ( or "Memory" ) resource reserved for node's pods from the node's allocatable "CPU" ( or "Memory" ) resource, upon failure is empty.
//   - the third return value, upon success is nil, upon failure is the coresponding error.
func GetNodeAllocatableAndAvailableQuantities(ctx context.Context, c clientset.Interface, n *v1.Node, resourceName v1.ResourceName) (resource.Quantity, resource.Quantity, error) {
	var nodeAllocatable, podAllocated, nodeAvailable resource.Quantity
	switch resourceName {
	case v1.ResourceCPU:
		nodeAllocatable = n.Status.Allocatable.Cpu().DeepCopy()
	case v1.ResourceMemory:
		nodeAllocatable = n.Status.Allocatable.Memory().DeepCopy()
	default:
		return resource.Quantity{}, resource.Quantity{}, fmt.Errorf("unexpected resource type %q; expected either 'CPU' or 'Memory'", resourceName)
	}

	if n.Status.Allocatable == nil {
		return resource.Quantity{}, resource.Quantity{}, fmt.Errorf("unexpected empty value of allocatable, while attempting to get node's allocatable %s", resourceName.String())
	}

	// Exclude pods that are in the Succeeded or Failed states
	selector := fmt.Sprintf("spec.nodeName=%s,status.phase!=%v,status.phase!=%v", n.Name, v1.PodSucceeded, v1.PodFailed)
	listOptions := metav1.ListOptions{FieldSelector: selector}
	podList, err := c.CoreV1().Pods(metav1.NamespaceAll).List(ctx, listOptions)
	if err != nil {
		return resource.Quantity{}, resource.Quantity{}, fmt.Errorf("error getting list of pods: %w, while attempting to get node's allocatable %s", err, resourceName.String())
	}

	for _, pod := range podList.Items {
		podRequest := resourceapi.GetResourceRequestQuantity(&pod, resourceName)
		podAllocated.Add(podRequest)
	}