Use List objects for metrics in kubectl top and HPA

This commit is contained in:
mksalawa 2016-08-19 14:18:59 +02:00
parent 4b598fec0c
commit 2833119a15
7 changed files with 156 additions and 115 deletions

View File

@ -284,9 +284,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
var heapsterRawMemResponse []byte var heapsterRawMemResponse []byte
if tc.useMetricsApi { if tc.useMetricsApi {
metrics := []*metrics_api.PodMetrics{} metrics := metrics_api.PodMetricsList{}
for i, cpu := range tc.reportedLevels { for i, cpu := range tc.reportedLevels {
podMetric := &metrics_api.PodMetrics{ podMetric := metrics_api.PodMetrics{
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: fmt.Sprintf("%s-%d", podNamePrefix, i), Name: fmt.Sprintf("%s-%d", podNamePrefix, i),
Namespace: namespace, 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) heapsterRawMemResponse, _ = json.Marshal(&metrics)
} else { } else {

View File

@ -166,15 +166,15 @@ func (h *HeapsterMetricsClient) getCpuUtilizationForPods(namespace string, selec
glog.V(4).Infof("Heapster metrics result: %s", string(resultRaw)) 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) err = json.Unmarshal(resultRaw, &metrics)
if err != nil { if err != nil {
return 0, time.Time{}, fmt.Errorf("failed to unmarshall heapster response: %v", err) 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() present := sets.NewString()
for _, m := range metrics { for _, m := range metrics.Items {
present.Insert(m.Name) present.Insert(m.Name)
} }
missing := make([]string, 0) missing := make([]string, 0)
@ -187,11 +187,11 @@ func (h *HeapsterMetricsClient) getCpuUtilizationForPods(namespace string, selec
if len(missing) > 0 { if len(missing) > 0 {
hint = fmt.Sprintf(" (sample missing pod: %s/%s)", namespace, 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) sum := int64(0)
for _, m := range metrics { for _, m := range metrics.Items {
if _, found := podNames[m.Name]; found { if _, found := podNames[m.Name]; found {
for _, c := range m.Containers { for _, c := range m.Containers {
cpu, found := c.Usage[v1.ResourceCPU] 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 // GetCustomMetric returns the average value of the given custom metric from the

View File

@ -102,9 +102,9 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
if tc.useMetricsApi { if tc.useMetricsApi {
fakeClient.AddProxyReactor("services", func(action core.Action) (handled bool, ret restclient.ResponseWrapper, err error) { 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 { for i, containers := range tc.reportedPodMetrics {
metric := &metrics_api.PodMetrics{ metric := metrics_api.PodMetrics{
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: fmt.Sprintf("%s-%d", podNamePrefix, i), Name: fmt.Sprintf("%s-%d", podNamePrefix, i),
Namespace: namespace, Namespace: namespace,
@ -126,7 +126,7 @@ func (tc *testCase) prepareTestClient(t *testing.T) *fake.Clientset {
} }
metric.Containers = append(metric.Containers, cm) metric.Containers = append(metric.Containers, cm)
} }
metrics = append(metrics, metric) metrics.Items = append(metrics.Items, metric)
} }
heapsterRawMemResponse, _ := json.Marshal(&metrics) heapsterRawMemResponse, _ := json.Marshal(&metrics)
return true, newFakeResponseWrapper(heapsterRawMemResponse), nil return true, newFakeResponseWrapper(heapsterRawMemResponse), nil

View File

@ -28,6 +28,7 @@ import (
"k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/client/unversioned/fake"
"net/url" "net/url"
"k8s.io/heapster/metrics/apis/metrics/v1alpha1"
) )
const ( const (
@ -70,7 +71,7 @@ func TestTopNodeAllMetrics(t *testing.T) {
// Check the presence of node names in the output. // Check the presence of node names in the output.
result := buf.String() result := buf.String()
for _, m := range metrics { for _, m := range metrics.Items {
if !strings.Contains(result, m.Name) { if !strings.Contains(result, m.Name) {
t.Errorf("missing metrics for %s: \n%s", m.Name, result) 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) { func TestTopNodeWithNameMetrics(t *testing.T) {
initTestErrorHandler(t) initTestErrorHandler(t)
metrics, nodes := testNodeMetricsData() metrics, nodes := testNodeMetricsData()
expectedMetrics := metrics[0] expectedMetrics := metrics.Items[0]
expectedNode := &nodes.Items[0] expectedNode := nodes.Items[0]
nonExpectedMetrics := metrics[1:] nonExpectedMetrics := v1alpha1.NodeMetricsList{
ListMeta: metrics.ListMeta,
Items: metrics.Items[1:],
}
expectedPath := fmt.Sprintf("%s/%s/nodes/%s", baseMetricsAddress, metricsApiVersion, expectedMetrics.Name) expectedPath := fmt.Sprintf("%s/%s/nodes/%s", baseMetricsAddress, metricsApiVersion, expectedMetrics.Name)
expectedNodePath := fmt.Sprintf("/%s/%s/nodes/%s", apiPrefix, apiVersion, 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 return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil
case p == expectedNodePath && m == "GET": 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: default:
t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath) t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath)
return nil, nil return nil, nil
@ -118,7 +122,7 @@ func TestTopNodeWithNameMetrics(t *testing.T) {
if !strings.Contains(result, expectedMetrics.Name) { if !strings.Contains(result, expectedMetrics.Name) {
t.Errorf("missing metrics for %s: \n%s", expectedMetrics.Name, result) 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) { if strings.Contains(result, m.Name) {
t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) 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) { func TestTopNodeWithLabelSelectorMetrics(t *testing.T) {
initTestErrorHandler(t) initTestErrorHandler(t)
metrics, nodes := testNodeMetricsData() metrics, nodes := testNodeMetricsData()
expectedMetrics := metrics[0:1] expectedMetrics := v1alpha1.NodeMetricsList{
expectedNodes := &api.NodeList{ ListMeta: metrics.ListMeta,
Items: metrics.Items[0:1],
}
expectedNodes := api.NodeList{
ListMeta: nodes.ListMeta, ListMeta: nodes.ListMeta,
Items: nodes.Items[0:1], Items: nodes.Items[0:1],
} }
nonExpectedMetrics := metrics[1:] nonExpectedMetrics := v1alpha1.NodeMetricsList{
ListMeta: metrics.ListMeta,
Items: metrics.Items[1:],
}
label := "key=value" label := "key=value"
expectedPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion) expectedPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion)
expectedQuery := fmt.Sprintf("labelSelector=%s", url.QueryEscape(label)) 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 return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil
case p == expectedNodePath && m == "GET": 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: default:
t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath) t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath)
return nil, nil return nil, nil
@ -169,12 +179,12 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) {
// Check the presence of node names in the output. // Check the presence of node names in the output.
result := buf.String() result := buf.String()
for _, m := range expectedMetrics { for _, m := range expectedMetrics.Items {
if !strings.Contains(result, m.Name) { if !strings.Contains(result, m.Name) {
t.Errorf("missing metrics for %s: \n%s", m.Name, result) 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) { if strings.Contains(result, m.Name) {
t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) t.Errorf("unexpected metrics for %s: \n%s", m.Name, result)
} }

View File

@ -23,6 +23,7 @@ import (
"strings" "strings"
"testing" "testing"
metrics_api "k8s.io/heapster/metrics/apis/metrics/v1alpha1"
"k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/client/restclient" "k8s.io/kubernetes/pkg/client/restclient"
"k8s.io/kubernetes/pkg/client/unversioned/fake" "k8s.io/kubernetes/pkg/client/unversioned/fake"
@ -35,12 +36,18 @@ func TestTopPodAllInNamespaceMetrics(t *testing.T) {
metrics := testPodMetricsData() metrics := testPodMetricsData()
testNamespace := "testnamespace" testNamespace := "testnamespace"
nonTestNamespace := "anothernamespace" nonTestNamespace := "anothernamespace"
expectedMetrics := metrics[0:2] expectedMetrics := metrics_api.PodMetricsList{
for _, m := range expectedMetrics { ListMeta: metrics.ListMeta,
Items: metrics.Items[0:2],
}
for _, m := range expectedMetrics.Items {
m.Namespace = testNamespace m.Namespace = testNamespace
} }
nonExpectedMetrics := metrics[2:] nonExpectedMetrics := metrics_api.PodMetricsList{
for _, m := range expectedMetrics { ListMeta: metrics.ListMeta,
Items: metrics.Items[2:],
}
for _, m := range expectedMetrics.Items {
m.Namespace = nonTestNamespace m.Namespace = nonTestNamespace
} }
expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods", baseMetricsAddress, metricsApiVersion, testNamespace) 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. // Check the presence of pod names in the output.
result := buf.String() result := buf.String()
for _, m := range expectedMetrics { for _, m := range expectedMetrics.Items {
if !strings.Contains(result, m.Name) { if !strings.Contains(result, m.Name) {
t.Errorf("missing metrics for %s: \n%s", m.Name, result) 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) { if strings.Contains(result, m.Name) {
t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) 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) { func TestTopPodWithNameMetrics(t *testing.T) {
initTestErrorHandler(t) initTestErrorHandler(t)
metrics := testPodMetricsData() metrics := testPodMetricsData()
expectedMetrics := metrics[0] expectedMetrics := metrics.Items[0]
nonExpectedMetrics := metrics[1:] nonExpectedMetrics := metrics_api.PodMetricsList{
ListMeta: metrics.ListMeta,
Items: metrics.Items[1:],
}
testNamespace := "testnamespace" testNamespace := "testnamespace"
expectedMetrics.Namespace = testNamespace expectedMetrics.Namespace = testNamespace
expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods/%s", baseMetricsAddress, metricsApiVersion, testNamespace, expectedMetrics.Name) 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) { if !strings.Contains(result, expectedMetrics.Name) {
t.Errorf("missing metrics for %s: \n%s", expectedMetrics.Name, result) 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) { if strings.Contains(result, m.Name) {
t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) 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) { func TestTopPodWithLabelSelectorMetrics(t *testing.T) {
initTestErrorHandler(t) initTestErrorHandler(t)
metrics := testPodMetricsData() metrics := testPodMetricsData()
expectedMetrics := metrics[0:2] expectedMetrics := metrics_api.PodMetricsList{
nonExpectedMetrics := metrics[2:] ListMeta: metrics.ListMeta,
Items: metrics.Items[0:2],
}
nonExpectedMetrics := metrics_api.PodMetricsList{
ListMeta: metrics.ListMeta,
Items: metrics.Items[2:],
}
label := "key=value" label := "key=value"
testNamespace := "testnamespace" testNamespace := "testnamespace"
expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods", baseMetricsAddress, metricsApiVersion, 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. // Check the presence of pod names in the output.
result := buf.String() result := buf.String()
for _, m := range expectedMetrics { for _, m := range expectedMetrics.Items {
if !strings.Contains(result, m.Name) { if !strings.Contains(result, m.Name) {
t.Errorf("missing metrics for %s: \n%s", m.Name, result) 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) { if strings.Contains(result, m.Name) {
t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) 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) { func TestTopPodWithContainersMetrics(t *testing.T) {
initTestErrorHandler(t) initTestErrorHandler(t)
metrics := testPodMetricsData() metrics := testPodMetricsData()
expectedMetrics := metrics[0] expectedMetrics := metrics.Items[0]
nonExpectedMetrics := metrics[1:] nonExpectedMetrics := metrics_api.PodMetricsList{
ListMeta: metrics.ListMeta,
Items: metrics.Items[1:],
}
testNamespace := "testnamespace" testNamespace := "testnamespace"
expectedMetrics.Namespace = testNamespace expectedMetrics.Namespace = testNamespace
expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods/%s", baseMetricsAddress, metricsApiVersion, testNamespace, expectedMetrics.Name) 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) 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) { if strings.Contains(result, m.Name) {
t.Errorf("unexpected metrics for %s: \n%s", m.Name, result) t.Errorf("unexpected metrics for %s: \n%s", m.Name, result)
} }

View File

@ -57,24 +57,29 @@ func marshallBody(metrics interface{}) (io.ReadCloser, error) {
return ioutil.NopCloser(bytes.NewReader(result)), nil return ioutil.NopCloser(bytes.NewReader(result)), nil
} }
func testNodeMetricsData() ([]metrics_api.NodeMetrics, *api.NodeList) { func testNodeMetricsData() (*metrics_api.NodeMetricsList, *api.NodeList) {
metrics := []metrics_api.NodeMetrics{ metrics := &metrics_api.NodeMetricsList{
{ ListMeta: unversioned.ListMeta{
ObjectMeta: v1.ObjectMeta{Name: "node1", ResourceVersion: "10"}, ResourceVersion: "1",
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),
},
}, },
{ Items: []metrics_api.NodeMetrics{
ObjectMeta: v1.ObjectMeta{Name: "node2", ResourceVersion: "11"}, {
Window: unversioned.Duration{Duration: time.Minute}, ObjectMeta: v1.ObjectMeta{Name: "node1", ResourceVersion: "10"},
Usage: v1.ResourceList{ Window: unversioned.Duration{Duration: time.Minute},
v1.ResourceCPU: *resource.NewMilliQuantity(5, resource.DecimalSI), Usage: v1.ResourceList{
v1.ResourceMemory: *resource.NewQuantity(6*(1024*1024), resource.DecimalSI), v1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI),
v1.ResourceStorage: *resource.NewQuantity(7*(1024*1024), 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 return metrics, nodes
} }
func testPodMetricsData() []metrics_api.PodMetrics { func testPodMetricsData() *metrics_api.PodMetricsList {
return []metrics_api.PodMetrics{ return &metrics_api.PodMetricsList{
{ ListMeta: unversioned.ListMeta{
ObjectMeta: v1.ObjectMeta{Name: "pod1", Namespace: "test", ResourceVersion: "10"}, ResourceVersion: "2",
Window: unversioned.Duration{Duration: time.Minute}, },
Containers: []metrics_api.ContainerMetrics{ Items: []metrics_api.PodMetrics{
{ {
Name: "container1-1", ObjectMeta: v1.ObjectMeta{Name: "pod1", Namespace: "test", ResourceVersion: "10"},
Usage: v1.ResourceList{ Window: unversioned.Duration{Duration: time.Minute},
v1.ResourceCPU: *resource.NewMilliQuantity(1, resource.DecimalSI), Containers: []metrics_api.ContainerMetrics{
v1.ResourceMemory: *resource.NewQuantity(2*(1024*1024), resource.DecimalSI), {
v1.ResourceStorage: *resource.NewQuantity(3*(1024*1024), resource.DecimalSI), 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",
Name: "container1-2", Usage: v1.ResourceList{
Usage: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(4, resource.DecimalSI),
v1.ResourceCPU: *resource.NewMilliQuantity(4, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(5*(1024*1024), resource.DecimalSI),
v1.ResourceMemory: *resource.NewQuantity(5*(1024*1024), resource.DecimalSI), v1.ResourceStorage: *resource.NewQuantity(6*(1024*1024), resource.DecimalSI),
v1.ResourceStorage: *resource.NewQuantity(6*(1024*1024), resource.DecimalSI), },
}, },
}, },
}, },
}, {
{ ObjectMeta: v1.ObjectMeta{Name: "pod2", Namespace: "test", ResourceVersion: "11"},
ObjectMeta: v1.ObjectMeta{Name: "pod2", Namespace: "test", ResourceVersion: "11"}, Window: unversioned.Duration{Duration: time.Minute},
Window: unversioned.Duration{Duration: time.Minute}, Containers: []metrics_api.ContainerMetrics{
Containers: []metrics_api.ContainerMetrics{ {
{ Name: "container2-1",
Name: "container2-1", Usage: v1.ResourceList{
Usage: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(7, resource.DecimalSI),
v1.ResourceCPU: *resource.NewMilliQuantity(7, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(8*(1024*1024), resource.DecimalSI),
v1.ResourceMemory: *resource.NewQuantity(8*(1024*1024), resource.DecimalSI), v1.ResourceStorage: *resource.NewQuantity(9*(1024*1024), resource.DecimalSI),
v1.ResourceStorage: *resource.NewQuantity(9*(1024*1024), resource.DecimalSI), },
}, },
}, {
{ Name: "container2-2",
Name: "container2-2", Usage: v1.ResourceList{
Usage: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(10, resource.DecimalSI),
v1.ResourceCPU: *resource.NewMilliQuantity(10, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(11*(1024*1024), resource.DecimalSI),
v1.ResourceMemory: *resource.NewQuantity(11*(1024*1024), resource.DecimalSI), v1.ResourceStorage: *resource.NewQuantity(12*(1024*1024), resource.DecimalSI),
v1.ResourceStorage: *resource.NewQuantity(12*(1024*1024), resource.DecimalSI), },
}, },
}, {
{ Name: "container2-3",
Name: "container2-3", Usage: v1.ResourceList{
Usage: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(13, resource.DecimalSI),
v1.ResourceCPU: *resource.NewMilliQuantity(13, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(14*(1024*1024), resource.DecimalSI),
v1.ResourceMemory: *resource.NewQuantity(14*(1024*1024), resource.DecimalSI), v1.ResourceStorage: *resource.NewQuantity(15*(1024*1024), resource.DecimalSI),
v1.ResourceStorage: *resource.NewQuantity(15*(1024*1024), resource.DecimalSI), },
}, },
}, },
}, },
}, {
{ ObjectMeta: v1.ObjectMeta{Name: "pod3", Namespace: "test", ResourceVersion: "12"},
ObjectMeta: v1.ObjectMeta{Name: "pod3", Namespace: "test", ResourceVersion: "12"}, Window: unversioned.Duration{Duration: time.Minute},
Window: unversioned.Duration{Duration: time.Minute}, Containers: []metrics_api.ContainerMetrics{
Containers: []metrics_api.ContainerMetrics{ {
{ Name: "container3-1",
Name: "container3-1", Usage: v1.ResourceList{
Usage: v1.ResourceList{ v1.ResourceCPU: *resource.NewMilliQuantity(7, resource.DecimalSI),
v1.ResourceCPU: *resource.NewMilliQuantity(7, resource.DecimalSI), v1.ResourceMemory: *resource.NewQuantity(8*(1024*1024), resource.DecimalSI),
v1.ResourceMemory: *resource.NewQuantity(8*(1024*1024), resource.DecimalSI), v1.ResourceStorage: *resource.NewQuantity(9*(1024*1024), resource.DecimalSI),
v1.ResourceStorage: *resource.NewQuantity(9*(1024*1024), resource.DecimalSI), },
}, },
}, },
}, },

View File

@ -105,10 +105,12 @@ func (cli *HeapsterMetricsClient) GetNodeMetrics(nodeName string, selector strin
} }
metrics := make([]metrics_api.NodeMetrics, 0) metrics := make([]metrics_api.NodeMetrics, 0)
if len(nodeName) == 0 { if len(nodeName) == 0 {
err = json.Unmarshal(resultRaw, &metrics) metricsList := metrics_api.NodeMetricsList{}
err = json.Unmarshal(resultRaw, &metricsList)
if err != nil { if err != nil {
return []metrics_api.NodeMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err) return []metrics_api.NodeMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err)
} }
metrics = append(metrics, metricsList.Items...)
} else { } else {
var singleMetric metrics_api.NodeMetrics var singleMetric metrics_api.NodeMetrics
err = json.Unmarshal(resultRaw, &singleMetric) err = json.Unmarshal(resultRaw, &singleMetric)
@ -148,12 +150,12 @@ func (cli *HeapsterMetricsClient) GetPodMetrics(namespace string, podName string
return []metrics_api.PodMetrics{}, err return []metrics_api.PodMetrics{}, err
} }
if len(podName) == 0 { if len(podName) == 0 {
metrics := make([]metrics_api.PodMetrics, 0) metrics := metrics_api.PodMetricsList{}
err = json.Unmarshal(resultRaw, &metrics) err = json.Unmarshal(resultRaw, &metrics)
if err != nil { if err != nil {
return []metrics_api.PodMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err) return []metrics_api.PodMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err)
} }
allMetrics = append(allMetrics, metrics...) allMetrics = append(allMetrics, metrics.Items...)
} else { } else {
var singleMetric metrics_api.PodMetrics var singleMetric metrics_api.PodMetrics
err = json.Unmarshal(resultRaw, &singleMetric) err = json.Unmarshal(resultRaw, &singleMetric)