mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-03 23:40:03 +00:00 
			
		
		
		
	Show resource limits with describe
Signed-off-by: Jason Sommer <jsdirv@gmail.com>
This commit is contained in:
		@@ -274,7 +274,7 @@ func describePod(pod *api.Pod, rcs []api.ReplicationController, events *api.Even
 | 
				
			|||||||
		fmt.Fprintf(out, "Status:\t%s\n", string(pod.Status.Phase))
 | 
							fmt.Fprintf(out, "Status:\t%s\n", string(pod.Status.Phase))
 | 
				
			||||||
		fmt.Fprintf(out, "Replication Controllers:\t%s\n", printReplicationControllersByLabels(rcs))
 | 
							fmt.Fprintf(out, "Replication Controllers:\t%s\n", printReplicationControllersByLabels(rcs))
 | 
				
			||||||
		fmt.Fprintf(out, "Containers:\n")
 | 
							fmt.Fprintf(out, "Containers:\n")
 | 
				
			||||||
		describeContainers(pod.Status.ContainerStatuses, out)
 | 
							describeContainers(pod, out)
 | 
				
			||||||
		if len(pod.Status.Conditions) > 0 {
 | 
							if len(pod.Status.Conditions) > 0 {
 | 
				
			||||||
			fmt.Fprint(out, "Conditions:\n  Type\tStatus\n")
 | 
								fmt.Fprint(out, "Conditions:\n  Type\tStatus\n")
 | 
				
			||||||
			for _, c := range pod.Status.Conditions {
 | 
								for _, c := range pod.Status.Conditions {
 | 
				
			||||||
@@ -336,39 +336,55 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string) (strin
 | 
				
			|||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func describeContainers(containers []api.ContainerStatus, out io.Writer) {
 | 
					func describeContainers(pod *api.Pod, out io.Writer) {
 | 
				
			||||||
	for _, container := range containers {
 | 
						statuses := map[string]api.ContainerStatus{}
 | 
				
			||||||
 | 
						for _, status := range pod.Status.ContainerStatuses {
 | 
				
			||||||
 | 
							statuses[status.Name] = status
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, container := range pod.Spec.Containers {
 | 
				
			||||||
 | 
							status := statuses[container.Name]
 | 
				
			||||||
 | 
							state := status.State
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fmt.Fprintf(out, "  %v:\n", container.Name)
 | 
							fmt.Fprintf(out, "  %v:\n", container.Name)
 | 
				
			||||||
		fmt.Fprintf(out, "    Image:\t%s\n", container.Image)
 | 
							fmt.Fprintf(out, "    Image:\t%s\n", container.Image)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if len(container.Resources.Limits) > 0 {
 | 
				
			||||||
 | 
								fmt.Fprintf(out, "    Limits:\n")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for name, quantity := range container.Resources.Limits {
 | 
				
			||||||
 | 
								fmt.Fprintf(out, "      %s:\t%s\n", name, quantity.String())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch {
 | 
							switch {
 | 
				
			||||||
		case container.State.Running != nil:
 | 
							case state.Running != nil:
 | 
				
			||||||
			fmt.Fprintf(out, "    State:\tRunning\n")
 | 
								fmt.Fprintf(out, "    State:\tRunning\n")
 | 
				
			||||||
			fmt.Fprintf(out, "      Started:\t%v\n", container.State.Running.StartedAt.Time.Format(time.RFC1123Z))
 | 
								fmt.Fprintf(out, "      Started:\t%v\n", state.Running.StartedAt.Time.Format(time.RFC1123Z))
 | 
				
			||||||
		case container.State.Waiting != nil:
 | 
							case state.Waiting != nil:
 | 
				
			||||||
			fmt.Fprintf(out, "    State:\tWaiting\n")
 | 
								fmt.Fprintf(out, "    State:\tWaiting\n")
 | 
				
			||||||
			if container.State.Waiting.Reason != "" {
 | 
								if state.Waiting.Reason != "" {
 | 
				
			||||||
				fmt.Fprintf(out, "      Reason:\t%s\n", container.State.Waiting.Reason)
 | 
									fmt.Fprintf(out, "      Reason:\t%s\n", state.Waiting.Reason)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case container.State.Terminated != nil:
 | 
							case state.Terminated != nil:
 | 
				
			||||||
			fmt.Fprintf(out, "    State:\tTerminated\n")
 | 
								fmt.Fprintf(out, "    State:\tTerminated\n")
 | 
				
			||||||
			if container.State.Terminated.Reason != "" {
 | 
								if state.Terminated.Reason != "" {
 | 
				
			||||||
				fmt.Fprintf(out, "      Reason:\t%s\n", container.State.Terminated.Reason)
 | 
									fmt.Fprintf(out, "      Reason:\t%s\n", state.Terminated.Reason)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if container.State.Terminated.Message != "" {
 | 
								if state.Terminated.Message != "" {
 | 
				
			||||||
				fmt.Fprintf(out, "      Message:\t%s\n", container.State.Terminated.Message)
 | 
									fmt.Fprintf(out, "      Message:\t%s\n", state.Terminated.Message)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			fmt.Fprintf(out, "      Exit Code:\t%d\n", container.State.Terminated.ExitCode)
 | 
								fmt.Fprintf(out, "      Exit Code:\t%d\n", state.Terminated.ExitCode)
 | 
				
			||||||
			if container.State.Terminated.Signal > 0 {
 | 
								if state.Terminated.Signal > 0 {
 | 
				
			||||||
				fmt.Fprintf(out, "      Signal:\t%d\n", container.State.Terminated.Signal)
 | 
									fmt.Fprintf(out, "      Signal:\t%d\n", state.Terminated.Signal)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			fmt.Fprintf(out, "      Started:\t%s\n", container.State.Terminated.StartedAt.Time.Format(time.RFC1123Z))
 | 
								fmt.Fprintf(out, "      Started:\t%s\n", state.Terminated.StartedAt.Time.Format(time.RFC1123Z))
 | 
				
			||||||
			fmt.Fprintf(out, "      Finished:\t%s\n", container.State.Terminated.FinishedAt.Time.Format(time.RFC1123Z))
 | 
								fmt.Fprintf(out, "      Finished:\t%s\n", state.Terminated.FinishedAt.Time.Format(time.RFC1123Z))
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			fmt.Fprintf(out, "    State:\tWaiting\n")
 | 
								fmt.Fprintf(out, "    State:\tWaiting\n")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fmt.Fprintf(out, "    Ready:\t%v\n", printBool(container.Ready))
 | 
							fmt.Fprintf(out, "    Ready:\t%v\n", printBool(status.Ready))
 | 
				
			||||||
		fmt.Fprintf(out, "    Restart Count:\t%d\n", container.RestartCount)
 | 
							fmt.Fprintf(out, "    Restart Count:\t%d\n", status.RestartCount)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
 | 
				
			||||||
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/client/testclient"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/client/testclient"
 | 
				
			||||||
	"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
						"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
 | 
				
			||||||
@@ -119,12 +120,14 @@ func TestPodDescribeResultsSorted(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestDescribeContainers(t *testing.T) {
 | 
					func TestDescribeContainers(t *testing.T) {
 | 
				
			||||||
	testCases := []struct {
 | 
						testCases := []struct {
 | 
				
			||||||
		input            api.ContainerStatus
 | 
							container        api.Container
 | 
				
			||||||
 | 
							status           api.ContainerStatus
 | 
				
			||||||
		expectedElements []string
 | 
							expectedElements []string
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		// Running state.
 | 
							// Running state.
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			input: api.ContainerStatus{
 | 
								container: api.Container{Name: "test", Image: "image"},
 | 
				
			||||||
 | 
								status: api.ContainerStatus{
 | 
				
			||||||
				Name: "test",
 | 
									Name: "test",
 | 
				
			||||||
				State: api.ContainerState{
 | 
									State: api.ContainerState{
 | 
				
			||||||
					Running: &api.ContainerStateRunning{
 | 
										Running: &api.ContainerStateRunning{
 | 
				
			||||||
@@ -133,13 +136,13 @@ func TestDescribeContainers(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				Ready:        true,
 | 
									Ready:        true,
 | 
				
			||||||
				RestartCount: 7,
 | 
									RestartCount: 7,
 | 
				
			||||||
				Image:        "image",
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedElements: []string{"test", "State", "Running", "Ready", "True", "Restart Count", "7", "Image", "image", "Started"},
 | 
								expectedElements: []string{"test", "State", "Running", "Ready", "True", "Restart Count", "7", "Image", "image", "Started"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		// Waiting state.
 | 
							// Waiting state.
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			input: api.ContainerStatus{
 | 
								container: api.Container{Name: "test", Image: "image"},
 | 
				
			||||||
 | 
								status: api.ContainerStatus{
 | 
				
			||||||
				Name: "test",
 | 
									Name: "test",
 | 
				
			||||||
				State: api.ContainerState{
 | 
									State: api.ContainerState{
 | 
				
			||||||
					Waiting: &api.ContainerStateWaiting{
 | 
										Waiting: &api.ContainerStateWaiting{
 | 
				
			||||||
@@ -148,13 +151,13 @@ func TestDescribeContainers(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				Ready:        true,
 | 
									Ready:        true,
 | 
				
			||||||
				RestartCount: 7,
 | 
									RestartCount: 7,
 | 
				
			||||||
				Image:        "image",
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato"},
 | 
								expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		// Terminated state.
 | 
							// Terminated state.
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			input: api.ContainerStatus{
 | 
								container: api.Container{Name: "test", Image: "image"},
 | 
				
			||||||
 | 
								status: api.ContainerStatus{
 | 
				
			||||||
				Name: "test",
 | 
									Name: "test",
 | 
				
			||||||
				State: api.ContainerState{
 | 
									State: api.ContainerState{
 | 
				
			||||||
					Terminated: &api.ContainerStateTerminated{
 | 
										Terminated: &api.ContainerStateTerminated{
 | 
				
			||||||
@@ -166,25 +169,52 @@ func TestDescribeContainers(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
				Ready:        true,
 | 
									Ready:        true,
 | 
				
			||||||
				RestartCount: 7,
 | 
									RestartCount: 7,
 | 
				
			||||||
				Image:        "image",
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedElements: []string{"test", "State", "Terminated", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato", "Started", "Finished", "Exit Code", "2"},
 | 
								expectedElements: []string{"test", "State", "Terminated", "Ready", "True", "Restart Count", "7", "Image", "image", "Reason", "potato", "Started", "Finished", "Exit Code", "2"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		// No state defaults to waiting.
 | 
							// No state defaults to waiting.
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			input: api.ContainerStatus{
 | 
								container: api.Container{Name: "test", Image: "image"},
 | 
				
			||||||
 | 
								status: api.ContainerStatus{
 | 
				
			||||||
				Name:         "test",
 | 
									Name:         "test",
 | 
				
			||||||
				Ready:        true,
 | 
									Ready:        true,
 | 
				
			||||||
				RestartCount: 7,
 | 
									RestartCount: 7,
 | 
				
			||||||
				Image:        "image",
 | 
					 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image"},
 | 
								expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image"},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							// Using limits.
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								container: api.Container{
 | 
				
			||||||
 | 
									Name:  "test",
 | 
				
			||||||
 | 
									Image: "image",
 | 
				
			||||||
 | 
									Resources: api.ResourceRequirements{
 | 
				
			||||||
 | 
										Limits: api.ResourceList{
 | 
				
			||||||
 | 
											api.ResourceName(api.ResourceCPU):     resource.MustParse("1000"),
 | 
				
			||||||
 | 
											api.ResourceName(api.ResourceMemory):  resource.MustParse("4G"),
 | 
				
			||||||
 | 
											api.ResourceName(api.ResourceStorage): resource.MustParse("20G"),
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								status: api.ContainerStatus{
 | 
				
			||||||
 | 
									Name:         "test",
 | 
				
			||||||
 | 
									Ready:        true,
 | 
				
			||||||
 | 
									RestartCount: 7,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								expectedElements: []string{"cpu", "1k", "memory", "4G", "storage", "20G"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i, testCase := range testCases {
 | 
						for i, testCase := range testCases {
 | 
				
			||||||
		out := new(bytes.Buffer)
 | 
							out := new(bytes.Buffer)
 | 
				
			||||||
		describeContainers([]api.ContainerStatus{testCase.input}, out)
 | 
							pod := api.Pod{
 | 
				
			||||||
 | 
								Spec: api.PodSpec{
 | 
				
			||||||
 | 
									Containers: []api.Container{testCase.container},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								Status: api.PodStatus{
 | 
				
			||||||
 | 
									ContainerStatuses: []api.ContainerStatus{testCase.status},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							describeContainers(&pod, out)
 | 
				
			||||||
		output := out.String()
 | 
							output := out.String()
 | 
				
			||||||
		for _, expected := range testCase.expectedElements {
 | 
							for _, expected := range testCase.expectedElements {
 | 
				
			||||||
			if !strings.Contains(output, expected) {
 | 
								if !strings.Contains(output, expected) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user