mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Make kubectl describe node include allocated resource
This commit is contained in:
		@@ -301,6 +301,14 @@ func (q *Quantity) String() string {
 | 
			
		||||
	return number + string(suffix)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (q *Quantity) Add(y Quantity) error {
 | 
			
		||||
	if q.Format != y.Format {
 | 
			
		||||
		return fmt.Errorf("format mismatch: %v vs. %v", q.Format, y.Format)
 | 
			
		||||
	}
 | 
			
		||||
	q.Amount.Add(q.Amount, y.Amount)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalJSON implements the json.Marshaller interface.
 | 
			
		||||
func (q Quantity) MarshalJSON() ([]byte, error) {
 | 
			
		||||
	return []byte(`"` + q.String() + `"`), nil
 | 
			
		||||
 
 | 
			
		||||
@@ -870,6 +870,17 @@ func describeNode(node *api.Node, pods []*api.Pod, events *api.EventList) (strin
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		runningPods := filterNonRunningPods(pods)
 | 
			
		||||
		reqs, err := getPodsTotalRequests(runningPods)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Fprintf(out, "Allocated resources (total requests):\n")
 | 
			
		||||
		for reqResource, reqValue := range reqs {
 | 
			
		||||
			fmt.Fprintf(out, " %s:\t%s\n", reqResource, reqValue.String())
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Fprintf(out, " pods:\t%d\n", len(runningPods))
 | 
			
		||||
 | 
			
		||||
		fmt.Fprintf(out, "Version:\n")
 | 
			
		||||
		fmt.Fprintf(out, " Kernel Version:\t%s\n", node.Status.NodeInfo.KernelVersion)
 | 
			
		||||
		fmt.Fprintf(out, " OS Image:\t%s\n", node.Status.NodeInfo.OsImage)
 | 
			
		||||
@@ -918,6 +929,52 @@ func describeNode(node *api.Node, pods []*api.Pod, events *api.EventList) (strin
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func filterNonRunningPods(pods []*api.Pod) []*api.Pod {
 | 
			
		||||
	if len(pods) == 0 {
 | 
			
		||||
		return pods
 | 
			
		||||
	}
 | 
			
		||||
	result := []*api.Pod{}
 | 
			
		||||
	for _, pod := range pods {
 | 
			
		||||
		if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		result = append(result, pod)
 | 
			
		||||
	}
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getPodsTotalRequests(pods []*api.Pod) (map[api.ResourceName]resource.Quantity, error) {
 | 
			
		||||
	reqs := map[api.ResourceName]resource.Quantity{}
 | 
			
		||||
	for _, pod := range pods {
 | 
			
		||||
		podReqs, err := getSinglePodTotalRequests(pod)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		for podReqName, podReqValue := range podReqs {
 | 
			
		||||
			if value, ok := reqs[podReqName]; !ok {
 | 
			
		||||
				reqs[podReqName] = podReqValue
 | 
			
		||||
			} else if err = value.Add(podReqValue); err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return reqs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getSinglePodTotalRequests(pod *api.Pod) (map[api.ResourceName]resource.Quantity, error) {
 | 
			
		||||
	reqs := map[api.ResourceName]resource.Quantity{}
 | 
			
		||||
	for _, container := range pod.Spec.Containers {
 | 
			
		||||
		for name, quantity := range container.Resources.Requests {
 | 
			
		||||
			if value, ok := reqs[name]; !ok {
 | 
			
		||||
				reqs[name] = quantity
 | 
			
		||||
			} else if err := value.Add(quantity); err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return reqs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DescribeEvents(el *api.EventList, w io.Writer) {
 | 
			
		||||
	if len(el.Items) == 0 {
 | 
			
		||||
		fmt.Fprint(w, "No events.")
 | 
			
		||||
 
 | 
			
		||||
@@ -336,3 +336,78 @@ func TestDefaultDescribers(t *testing.T) {
 | 
			
		||||
		t.Errorf("unexpected output: %s", out)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetPodsTotalRequests(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		pods         []*api.Pod
 | 
			
		||||
		expectedReqs map[api.ResourceName]resource.Quantity
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			pods: []*api.Pod{
 | 
			
		||||
				{
 | 
			
		||||
					Spec: api.PodSpec{
 | 
			
		||||
						Containers: []api.Container{
 | 
			
		||||
							{
 | 
			
		||||
								Resources: api.ResourceRequirements{
 | 
			
		||||
									Requests: api.ResourceList{
 | 
			
		||||
										api.ResourceName(api.ResourceCPU):     resource.MustParse("1"),
 | 
			
		||||
										api.ResourceName(api.ResourceMemory):  resource.MustParse("300Mi"),
 | 
			
		||||
										api.ResourceName(api.ResourceStorage): resource.MustParse("1G"),
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							{
 | 
			
		||||
								Resources: api.ResourceRequirements{
 | 
			
		||||
									Requests: api.ResourceList{
 | 
			
		||||
										api.ResourceName(api.ResourceCPU):     resource.MustParse("90m"),
 | 
			
		||||
										api.ResourceName(api.ResourceMemory):  resource.MustParse("120Mi"),
 | 
			
		||||
										api.ResourceName(api.ResourceStorage): resource.MustParse("200M"),
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Spec: api.PodSpec{
 | 
			
		||||
						Containers: []api.Container{
 | 
			
		||||
							{
 | 
			
		||||
								Resources: api.ResourceRequirements{
 | 
			
		||||
									Requests: api.ResourceList{
 | 
			
		||||
										api.ResourceName(api.ResourceCPU):     resource.MustParse("60m"),
 | 
			
		||||
										api.ResourceName(api.ResourceMemory):  resource.MustParse("43Mi"),
 | 
			
		||||
										api.ResourceName(api.ResourceStorage): resource.MustParse("500M"),
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
							{
 | 
			
		||||
								Resources: api.ResourceRequirements{
 | 
			
		||||
									Requests: api.ResourceList{
 | 
			
		||||
										api.ResourceName(api.ResourceCPU):     resource.MustParse("34m"),
 | 
			
		||||
										api.ResourceName(api.ResourceMemory):  resource.MustParse("83Mi"),
 | 
			
		||||
										api.ResourceName(api.ResourceStorage): resource.MustParse("700M"),
 | 
			
		||||
									},
 | 
			
		||||
								},
 | 
			
		||||
							},
 | 
			
		||||
						},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedReqs: map[api.ResourceName]resource.Quantity{
 | 
			
		||||
				api.ResourceName(api.ResourceCPU):     resource.MustParse("1.184"),
 | 
			
		||||
				api.ResourceName(api.ResourceMemory):  resource.MustParse("546Mi"),
 | 
			
		||||
				api.ResourceName(api.ResourceStorage): resource.MustParse("2.4G"),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, testCase := range testCases {
 | 
			
		||||
		reqs, err := getPodsTotalRequests(testCase.pods)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			t.Errorf("Unexpected error %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		if !reflect.DeepEqual(reqs, testCase.expectedReqs) {
 | 
			
		||||
			t.Errorf("Expected %v, got %v", testCase.expectedReqs, reqs)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user