mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-31 07:20:13 +00:00
Merge pull request #12005 from JanetKuo/kubectl-describe-allocatedresource
Make kubectl describe node include allocated resource
This commit is contained in:
commit
785ccf4a74
@ -301,6 +301,14 @@ func (q *Quantity) String() string {
|
|||||||
return number + string(suffix)
|
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.
|
// MarshalJSON implements the json.Marshaller interface.
|
||||||
func (q Quantity) MarshalJSON() ([]byte, error) {
|
func (q Quantity) MarshalJSON() ([]byte, error) {
|
||||||
return []byte(`"` + q.String() + `"`), nil
|
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, "Version:\n")
|
||||||
fmt.Fprintf(out, " Kernel Version:\t%s\n", node.Status.NodeInfo.KernelVersion)
|
fmt.Fprintf(out, " Kernel Version:\t%s\n", node.Status.NodeInfo.KernelVersion)
|
||||||
fmt.Fprintf(out, " OS Image:\t%s\n", node.Status.NodeInfo.OsImage)
|
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) {
|
func DescribeEvents(el *api.EventList, w io.Writer) {
|
||||||
if len(el.Items) == 0 {
|
if len(el.Items) == 0 {
|
||||||
fmt.Fprint(w, "No events.")
|
fmt.Fprint(w, "No events.")
|
||||||
|
@ -336,3 +336,78 @@ func TestDefaultDescribers(t *testing.T) {
|
|||||||
t.Errorf("unexpected output: %s", out)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user