From 2833119a1502f17892cdb548b55e8859f1faeaaf Mon Sep 17 00:00:00 2001 From: mksalawa Date: Fri, 19 Aug 2016 14:18:59 +0200 Subject: [PATCH] Use List objects for metrics in kubectl top and HPA --- .../podautoscaler/horizontal_test.go | 6 +- .../podautoscaler/metrics/metrics_client.go | 12 +- .../metrics/metrics_client_test.go | 6 +- pkg/kubectl/cmd/top_node_test.go | 34 ++-- pkg/kubectl/cmd/top_pod_test.go | 51 ++++-- pkg/kubectl/cmd/top_test.go | 154 ++++++++++-------- pkg/kubectl/metricsutil/metrics_client.go | 8 +- 7 files changed, 156 insertions(+), 115 deletions(-) diff --git a/pkg/controller/podautoscaler/horizontal_test.go b/pkg/controller/podautoscaler/horizontal_test.go index f8174c20cde..884beec0d26 100644 --- a/pkg/controller/podautoscaler/horizontal_test.go +++ b/pkg/controller/podautoscaler/horizontal_test.go @@ -284,9 +284,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { var heapsterRawMemResponse []byte if tc.useMetricsApi { - metrics := []*metrics_api.PodMetrics{} + metrics := metrics_api.PodMetricsList{} for i, cpu := range tc.reportedLevels { - podMetric := &metrics_api.PodMetrics{ + podMetric := metrics_api.PodMetrics{ ObjectMeta: v1.ObjectMeta{ Name: fmt.Sprintf("%s-%d", podNamePrefix, i), Namespace: namespace, @@ -306,7 +306,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { }, }, } - metrics = append(metrics, podMetric) + metrics.Items = append(metrics.Items, podMetric) } heapsterRawMemResponse, _ = json.Marshal(&metrics) } else { diff --git a/pkg/controller/podautoscaler/metrics/metrics_client.go b/pkg/controller/podautoscaler/metrics/metrics_client.go index 9319ab3086a..0ad555a4ab9 100644 --- a/pkg/controller/podautoscaler/metrics/metrics_client.go +++ b/pkg/controller/podautoscaler/metrics/metrics_client.go @@ -166,15 +166,15 @@ func (h *HeapsterMetricsClient) getCpuUtilizationForPods(namespace string, selec glog.V(4).Infof("Heapster metrics result: %s", string(resultRaw)) - metrics := make([]metrics_api.PodMetrics, 0) + metrics := metrics_api.PodMetricsList{} err = json.Unmarshal(resultRaw, &metrics) if err != nil { return 0, time.Time{}, fmt.Errorf("failed to unmarshall heapster response: %v", err) } - if len(metrics) != len(podNames) { + if len(metrics.Items) != len(podNames) { present := sets.NewString() - for _, m := range metrics { + for _, m := range metrics.Items { present.Insert(m.Name) } missing := make([]string, 0) @@ -187,11 +187,11 @@ func (h *HeapsterMetricsClient) getCpuUtilizationForPods(namespace string, selec if len(missing) > 0 { hint = fmt.Sprintf(" (sample missing pod: %s/%s)", namespace, missing[0]) } - return 0, time.Time{}, fmt.Errorf("metrics obtained for %d/%d of pods%s", len(metrics), len(podNames), hint) + return 0, time.Time{}, fmt.Errorf("metrics obtained for %d/%d of pods%s", len(metrics.Items), len(podNames), hint) } sum := int64(0) - for _, m := range metrics { + for _, m := range metrics.Items { if _, found := podNames[m.Name]; found { for _, c := range m.Containers { cpu, found := c.Usage[v1.ResourceCPU] @@ -205,7 +205,7 @@ func (h *HeapsterMetricsClient) getCpuUtilizationForPods(namespace string, selec } } - return sum / int64(len(metrics)), metrics[0].Timestamp.Time, nil + return sum / int64(len(metrics.Items)), metrics.Items[0].Timestamp.Time, nil } // GetCustomMetric returns the average value of the given custom metric from the diff --git a/pkg/controller/podautoscaler/metrics/metrics_client_test.go b/pkg/controller/podautoscaler/metrics/metrics_client_test.go index ed3d8f3cf8d..1ac615530e7 100644 --- a/pkg/controller/podautoscaler/metrics/metrics_client_test.go +++ b/pkg/controller/podautoscaler/metrics/metrics_client_test.go @@ -102,9 +102,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { if tc.useMetricsApi { fakeClient.AddProxyReactor("services", func(action core.Action) (handled bool, ret restclient.ResponseWrapper, err error) { - metrics := []*metrics_api.PodMetrics{} + metrics := metrics_api.PodMetricsList{} for i, containers := range tc.reportedPodMetrics { - metric := &metrics_api.PodMetrics{ + metric := metrics_api.PodMetrics{ ObjectMeta: v1.ObjectMeta{ Name: fmt.Sprintf("%s-%d", podNamePrefix, i), Namespace: namespace, @@ -126,7 +126,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset { } metric.Containers = append(metric.Containers, cm) } - metrics = append(metrics, metric) + metrics.Items = append(metrics.Items, metric) } heapsterRawMemResponse, _ := json.Marshal(&metrics) return true, newFakeResponseWrapper(heapsterRawMemResponse), nil diff --git a/pkg/kubectl/cmd/top_node_test.go b/pkg/kubectl/cmd/top_node_test.go index 787ffe3f397..c527458b8de 100644 --- a/pkg/kubectl/cmd/top_node_test.go +++ b/pkg/kubectl/cmd/top_node_test.go @@ -28,6 +28,7 @@ import ( "k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/unversioned/fake" "net/url" + "k8s.io/heapster/metrics/apis/metrics/v1alpha1" ) const ( @@ -70,7 +71,7 @@ func TestTopNodeAllMetrics(t *testing.T) { // Check the presence of node names in the output. result := buf.String() - for _, m := range metrics { + for _, m := range metrics.Items { if !strings.Contains(result, m.Name) { t.Errorf("missing metrics for %s: \n%s", m.Name, result) } @@ -80,9 +81,12 @@ func TestTopNodeAllMetrics(t *testing.T) { func TestTopNodeWithNameMetrics(t *testing.T) { initTestErrorHandler(t) metrics, nodes := testNodeMetricsData() - expectedMetrics := metrics[0] - expectedNode := &nodes.Items[0] - nonExpectedMetrics := metrics[1:] + expectedMetrics := metrics.Items[0] + expectedNode := nodes.Items[0] + nonExpectedMetrics := v1alpha1.NodeMetricsList{ + ListMeta: metrics.ListMeta, + Items: metrics.Items[1:], + } expectedPath := fmt.Sprintf("%s/%s/nodes/%s", baseMetricsAddress, metricsApiVersion, expectedMetrics.Name) expectedNodePath := fmt.Sprintf("/%s/%s/nodes/%s", apiPrefix, apiVersion, expectedMetrics.Name) @@ -99,7 +103,7 @@ func TestTopNodeWithNameMetrics(t *testing.T) { } return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil case p == expectedNodePath && m == "GET": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, expectedNode)}, nil + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &expectedNode)}, nil default: t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath) return nil, nil @@ -118,7 +122,7 @@ func TestTopNodeWithNameMetrics(t *testing.T) { if !strings.Contains(result, expectedMetrics.Name) { t.Errorf("missing metrics for %s: \n%s", expectedMetrics.Name, result) } - for _, m := range nonExpectedMetrics { + for _, m := range nonExpectedMetrics.Items { if strings.Contains(result, m.Name) { t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) } @@ -128,12 +132,18 @@ func TestTopNodeWithNameMetrics(t *testing.T) { func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { initTestErrorHandler(t) metrics, nodes := testNodeMetricsData() - expectedMetrics := metrics[0:1] - expectedNodes := &api.NodeList{ + expectedMetrics := v1alpha1.NodeMetricsList{ + ListMeta: metrics.ListMeta, + Items: metrics.Items[0:1], + } + expectedNodes := api.NodeList{ ListMeta: nodes.ListMeta, Items: nodes.Items[0:1], } - nonExpectedMetrics := metrics[1:] + nonExpectedMetrics := v1alpha1.NodeMetricsList{ + ListMeta: metrics.ListMeta, + Items: metrics.Items[1:], + } label := "key=value" expectedPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion) expectedQuery := fmt.Sprintf("labelSelector=%s", url.QueryEscape(label)) @@ -152,7 +162,7 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { } return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil case p == expectedNodePath && m == "GET": - return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, expectedNodes)}, nil + return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &expectedNodes)}, nil default: t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath) return nil, nil @@ -169,12 +179,12 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) { // Check the presence of node names in the output. result := buf.String() - for _, m := range expectedMetrics { + for _, m := range expectedMetrics.Items { if !strings.Contains(result, m.Name) { t.Errorf("missing metrics for %s: \n%s", m.Name, result) } } - for _, m := range nonExpectedMetrics { + for _, m := range nonExpectedMetrics.Items { if strings.Contains(result, m.Name) { t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) } diff --git a/pkg/kubectl/cmd/top_pod_test.go b/pkg/kubectl/cmd/top_pod_test.go index fe9d5da658d..ccccc87344e 100644 --- a/pkg/kubectl/cmd/top_pod_test.go +++ b/pkg/kubectl/cmd/top_pod_test.go @@ -23,6 +23,7 @@ import ( "strings" "testing" + metrics_api "k8s.io/heapster/metrics/apis/metrics/v1alpha1" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/unversioned/fake" @@ -35,12 +36,18 @@ func TestTopPodAllInNamespaceMetrics(t *testing.T) { metrics := testPodMetricsData() testNamespace := "testnamespace" nonTestNamespace := "anothernamespace" - expectedMetrics := metrics[0:2] - for _, m := range expectedMetrics { + expectedMetrics := metrics_api.PodMetricsList{ + ListMeta: metrics.ListMeta, + Items: metrics.Items[0:2], + } + for _, m := range expectedMetrics.Items { m.Namespace = testNamespace } - nonExpectedMetrics := metrics[2:] - for _, m := range expectedMetrics { + nonExpectedMetrics := metrics_api.PodMetricsList{ + ListMeta: metrics.ListMeta, + Items: metrics.Items[2:], + } + for _, m := range expectedMetrics.Items { m.Namespace = nonTestNamespace } expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods", baseMetricsAddress, metricsApiVersion, testNamespace) @@ -72,12 +79,12 @@ func TestTopPodAllInNamespaceMetrics(t *testing.T) { // Check the presence of pod names in the output. result := buf.String() - for _, m := range expectedMetrics { + for _, m := range expectedMetrics.Items { if !strings.Contains(result, m.Name) { t.Errorf("missing metrics for %s: \n%s", m.Name, result) } } - for _, m := range nonExpectedMetrics { + for _, m := range nonExpectedMetrics.Items { if strings.Contains(result, m.Name) { t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) } @@ -87,8 +94,11 @@ func TestTopPodAllInNamespaceMetrics(t *testing.T) { func TestTopPodWithNameMetrics(t *testing.T) { initTestErrorHandler(t) metrics := testPodMetricsData() - expectedMetrics := metrics[0] - nonExpectedMetrics := metrics[1:] + expectedMetrics := metrics.Items[0] + nonExpectedMetrics := metrics_api.PodMetricsList{ + ListMeta: metrics.ListMeta, + Items: metrics.Items[1:], + } testNamespace := "testnamespace" expectedMetrics.Namespace = testNamespace expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods/%s", baseMetricsAddress, metricsApiVersion, testNamespace, expectedMetrics.Name) @@ -123,7 +133,7 @@ func TestTopPodWithNameMetrics(t *testing.T) { if !strings.Contains(result, expectedMetrics.Name) { t.Errorf("missing metrics for %s: \n%s", expectedMetrics.Name, result) } - for _, m := range nonExpectedMetrics { + for _, m := range nonExpectedMetrics.Items { if strings.Contains(result, m.Name) { t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) } @@ -133,8 +143,14 @@ func TestTopPodWithNameMetrics(t *testing.T) { func TestTopPodWithLabelSelectorMetrics(t *testing.T) { initTestErrorHandler(t) metrics := testPodMetricsData() - expectedMetrics := metrics[0:2] - nonExpectedMetrics := metrics[2:] + expectedMetrics := metrics_api.PodMetricsList{ + ListMeta: metrics.ListMeta, + Items: metrics.Items[0:2], + } + nonExpectedMetrics := metrics_api.PodMetricsList{ + ListMeta: metrics.ListMeta, + Items: metrics.Items[2:], + } label := "key=value" testNamespace := "testnamespace" expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods", baseMetricsAddress, metricsApiVersion, testNamespace) @@ -168,12 +184,12 @@ func TestTopPodWithLabelSelectorMetrics(t *testing.T) { // Check the presence of pod names in the output. result := buf.String() - for _, m := range expectedMetrics { + for _, m := range expectedMetrics.Items { if !strings.Contains(result, m.Name) { t.Errorf("missing metrics for %s: \n%s", m.Name, result) } } - for _, m := range nonExpectedMetrics { + for _, m := range nonExpectedMetrics.Items { if strings.Contains(result, m.Name) { t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) } @@ -183,8 +199,11 @@ func TestTopPodWithLabelSelectorMetrics(t *testing.T) { func TestTopPodWithContainersMetrics(t *testing.T) { initTestErrorHandler(t) metrics := testPodMetricsData() - expectedMetrics := metrics[0] - nonExpectedMetrics := metrics[1:] + expectedMetrics := metrics.Items[0] + nonExpectedMetrics := metrics_api.PodMetricsList{ + ListMeta: metrics.ListMeta, + Items: metrics.Items[1:], + } testNamespace := "testnamespace" expectedMetrics.Namespace = testNamespace expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods/%s", baseMetricsAddress, metricsApiVersion, testNamespace, expectedMetrics.Name) @@ -225,7 +244,7 @@ func TestTopPodWithContainersMetrics(t *testing.T) { t.Errorf("missing metrics for container %s: \n%s", m.Name, result) } } - for _, m := range nonExpectedMetrics { + for _, m := range nonExpectedMetrics.Items { if strings.Contains(result, m.Name) { t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) } diff --git a/pkg/kubectl/cmd/top_test.go b/pkg/kubectl/cmd/top_test.go index e381e492deb..8250c9f2ca2 100644 --- a/pkg/kubectl/cmd/top_test.go +++ b/pkg/kubectl/cmd/top_test.go @@ -57,24 +57,29 @@ func marshallBody(metrics interface{}) (io.ReadCloser, error) { return ioutil.NopCloser(bytes.NewReader(result)), nil } -func testNodeMetricsData() ([]metrics_api.NodeMetrics, *api.NodeList) { - metrics := []metrics_api.NodeMetrics{ - { - ObjectMeta: v1.ObjectMeta{Name: "node1", ResourceVersion: "10"}, - Window: unversioned.Duration{Duration: time.Minute}, - Usage: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(2*(1024*1024), resource.DecimalSI), - v1.ResourceStorage: *resource.NewQuantity(3*(1024*1024), resource.DecimalSI), - }, +func testNodeMetricsData() (*metrics_api.NodeMetricsList, *api.NodeList) { + metrics := &metrics_api.NodeMetricsList{ + ListMeta: unversioned.ListMeta{ + ResourceVersion: "1", }, - { - ObjectMeta: v1.ObjectMeta{Name: "node2", ResourceVersion: "11"}, - Window: unversioned.Duration{Duration: time.Minute}, - Usage: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(5, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(6*(1024*1024), resource.DecimalSI), - v1.ResourceStorage: *resource.NewQuantity(7*(1024*1024), resource.DecimalSI), + Items: []metrics_api.NodeMetrics{ + { + ObjectMeta: v1.ObjectMeta{Name: "node1", ResourceVersion: "10"}, + Window: unversioned.Duration{Duration: time.Minute}, + Usage: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(2*(1024*1024), resource.DecimalSI), + v1.ResourceStorage: *resource.NewQuantity(3*(1024*1024), resource.DecimalSI), + }, + }, + { + ObjectMeta: v1.ObjectMeta{Name: "node2", ResourceVersion: "11"}, + Window: unversioned.Duration{Duration: time.Minute}, + Usage: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(5, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(6*(1024*1024), resource.DecimalSI), + v1.ResourceStorage: *resource.NewQuantity(7*(1024*1024), resource.DecimalSI), + }, }, }, } @@ -108,70 +113,75 @@ func testNodeMetricsData() ([]metrics_api.NodeMetrics, *api.NodeList) { return metrics, nodes } -func testPodMetricsData() []metrics_api.PodMetrics { - return []metrics_api.PodMetrics{ - { - ObjectMeta: v1.ObjectMeta{Name: "pod1", Namespace: "test", ResourceVersion: "10"}, - Window: unversioned.Duration{Duration: time.Minute}, - Containers: []metrics_api.ContainerMetrics{ - { - Name: "container1-1", - Usage: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(2*(1024*1024), resource.DecimalSI), - v1.ResourceStorage: *resource.NewQuantity(3*(1024*1024), resource.DecimalSI), +func testPodMetricsData() *metrics_api.PodMetricsList { + return &metrics_api.PodMetricsList{ + ListMeta: unversioned.ListMeta{ + ResourceVersion: "2", + }, + Items: []metrics_api.PodMetrics{ + { + ObjectMeta: v1.ObjectMeta{Name: "pod1", Namespace: "test", ResourceVersion: "10"}, + Window: unversioned.Duration{Duration: time.Minute}, + Containers: []metrics_api.ContainerMetrics{ + { + Name: "container1-1", + Usage: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(2*(1024*1024), resource.DecimalSI), + v1.ResourceStorage: *resource.NewQuantity(3*(1024*1024), resource.DecimalSI), + }, }, - }, - { - Name: "container1-2", - Usage: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(4, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(5*(1024*1024), resource.DecimalSI), - v1.ResourceStorage: *resource.NewQuantity(6*(1024*1024), resource.DecimalSI), + { + Name: "container1-2", + Usage: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(4, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(5*(1024*1024), resource.DecimalSI), + v1.ResourceStorage: *resource.NewQuantity(6*(1024*1024), resource.DecimalSI), + }, }, }, }, - }, - { - ObjectMeta: v1.ObjectMeta{Name: "pod2", Namespace: "test", ResourceVersion: "11"}, - Window: unversioned.Duration{Duration: time.Minute}, - Containers: []metrics_api.ContainerMetrics{ - { - Name: "container2-1", - Usage: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(7, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(8*(1024*1024), resource.DecimalSI), - v1.ResourceStorage: *resource.NewQuantity(9*(1024*1024), resource.DecimalSI), + { + ObjectMeta: v1.ObjectMeta{Name: "pod2", Namespace: "test", ResourceVersion: "11"}, + Window: unversioned.Duration{Duration: time.Minute}, + Containers: []metrics_api.ContainerMetrics{ + { + Name: "container2-1", + Usage: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(7, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(8*(1024*1024), resource.DecimalSI), + v1.ResourceStorage: *resource.NewQuantity(9*(1024*1024), resource.DecimalSI), + }, }, - }, - { - Name: "container2-2", - Usage: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(10, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(11*(1024*1024), resource.DecimalSI), - v1.ResourceStorage: *resource.NewQuantity(12*(1024*1024), resource.DecimalSI), + { + Name: "container2-2", + Usage: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(10, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(11*(1024*1024), resource.DecimalSI), + v1.ResourceStorage: *resource.NewQuantity(12*(1024*1024), resource.DecimalSI), + }, }, - }, - { - Name: "container2-3", - Usage: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(13, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(14*(1024*1024), resource.DecimalSI), - v1.ResourceStorage: *resource.NewQuantity(15*(1024*1024), resource.DecimalSI), + { + Name: "container2-3", + Usage: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(13, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(14*(1024*1024), resource.DecimalSI), + v1.ResourceStorage: *resource.NewQuantity(15*(1024*1024), resource.DecimalSI), + }, }, }, }, - }, - { - ObjectMeta: v1.ObjectMeta{Name: "pod3", Namespace: "test", ResourceVersion: "12"}, - Window: unversioned.Duration{Duration: time.Minute}, - Containers: []metrics_api.ContainerMetrics{ - { - Name: "container3-1", - Usage: v1.ResourceList{ - v1.ResourceCPU: *resource.NewMilliQuantity(7, resource.DecimalSI), - v1.ResourceMemory: *resource.NewQuantity(8*(1024*1024), resource.DecimalSI), - v1.ResourceStorage: *resource.NewQuantity(9*(1024*1024), resource.DecimalSI), + { + ObjectMeta: v1.ObjectMeta{Name: "pod3", Namespace: "test", ResourceVersion: "12"}, + Window: unversioned.Duration{Duration: time.Minute}, + Containers: []metrics_api.ContainerMetrics{ + { + Name: "container3-1", + Usage: v1.ResourceList{ + v1.ResourceCPU: *resource.NewMilliQuantity(7, resource.DecimalSI), + v1.ResourceMemory: *resource.NewQuantity(8*(1024*1024), resource.DecimalSI), + v1.ResourceStorage: *resource.NewQuantity(9*(1024*1024), resource.DecimalSI), + }, }, }, }, diff --git a/pkg/kubectl/metricsutil/metrics_client.go b/pkg/kubectl/metricsutil/metrics_client.go index 5ff8752bbf6..b8394db87a7 100644 --- a/pkg/kubectl/metricsutil/metrics_client.go +++ b/pkg/kubectl/metricsutil/metrics_client.go @@ -105,10 +105,12 @@ func (cli *HeapsterMetricsClient) GetNodeMetrics(nodeName string, selector strin } metrics := make([]metrics_api.NodeMetrics, 0) if len(nodeName) == 0 { - err = json.Unmarshal(resultRaw, &metrics) + metricsList := metrics_api.NodeMetricsList{} + err = json.Unmarshal(resultRaw, &metricsList) if err != nil { return []metrics_api.NodeMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err) } + metrics = append(metrics, metricsList.Items...) } else { var singleMetric metrics_api.NodeMetrics err = json.Unmarshal(resultRaw, &singleMetric) @@ -148,12 +150,12 @@ func (cli *HeapsterMetricsClient) GetPodMetrics(namespace string, podName string return []metrics_api.PodMetrics{}, err } if len(podName) == 0 { - metrics := make([]metrics_api.PodMetrics, 0) + metrics := metrics_api.PodMetricsList{} err = json.Unmarshal(resultRaw, &metrics) if err != nil { return []metrics_api.PodMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err) } - allMetrics = append(allMetrics, metrics...) + allMetrics = append(allMetrics, metrics.Items...) } else { var singleMetric metrics_api.PodMetrics err = json.Unmarshal(resultRaw, &singleMetric)