diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 892d4f621f5..d22c9823f37 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -2464,13 +2464,13 @@ }, { "ImportPath": "k8s.io/heapster/metrics/api/v1/types", - "Comment": "v1.1.0-beta2", - "Rev": "9cb18ac0ceb193eb530a1fe339355c94ea454d85" + "Comment": "v1.2.0-beta.1", + "Rev": "c2ac40f1adf8c42a79badddb2a2acd673cae3bcb" }, { "ImportPath": "k8s.io/heapster/metrics/apis/metrics/v1alpha1", - "Comment": "v1.1.0-beta2", - "Rev": "9cb18ac0ceb193eb530a1fe339355c94ea454d85" + "Comment": "v1.2.0-beta.1", + "Rev": "c2ac40f1adf8c42a79badddb2a2acd673cae3bcb" } ] } diff --git a/cluster/addons/cluster-monitoring/google/heapster-controller.yaml b/cluster/addons/cluster-monitoring/google/heapster-controller.yaml index d33b9739636..42f54158b9a 100644 --- a/cluster/addons/cluster-monitoring/google/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/google/heapster-controller.yaml @@ -20,26 +20,26 @@ apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.1.0 + name: heapster-v1.2.0-beta.1 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" - version: v1.1.0 + version: v1.2.0-beta.1 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.1.0 + version: v1.2.0-beta.1 template: metadata: labels: k8s-app: heapster - version: v1.1.0 + version: v1.2.0-beta.1 spec: containers: - - image: gcr.io/google_containers/heapster:v1.1.0 + - image: gcr.io/google_containers/heapster:v1.2.0-beta.1 name: heapster resources: # keep request = limit to keep this container in guaranteed class @@ -57,7 +57,7 @@ spec: - name: ssl-certs mountPath: /etc/ssl/certs readOnly: true - - image: gcr.io/google_containers/heapster:v1.1.0 + - image: gcr.io/google_containers/heapster:v1.2.0-beta.1 name: eventer resources: # keep request = limit to keep this container in guaranteed class @@ -100,7 +100,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{metrics_memory_per_node}}Mi - --threshold=5 - - --deployment=heapster-v1.1.0 + - --deployment=heapster-v1.2.0-beta.1 - --container=heapster - --poll-period=300000 - --estimator=exponential @@ -129,7 +129,7 @@ spec: - --memory={{base_eventer_memory}} - --extra-memory={{eventer_memory_per_node}}Ki - --threshold=5 - - --deployment=heapster-v1.1.0 + - --deployment=heapster-v1.2.0-beta.1 - --container=eventer - --poll-period=300000 - --estimator=exponential diff --git a/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml b/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml index 5f73353e333..3dcdd625b90 100644 --- a/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml +++ b/cluster/addons/cluster-monitoring/googleinfluxdb/heapster-controller-combined.yaml @@ -20,26 +20,26 @@ apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.1.0 + name: heapster-v1.2.0-beta.1 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" - version: v1.1.0 + version: v1.2.0-beta.1 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.1.0 + version: v1.2.0-beta.1 template: metadata: labels: k8s-app: heapster - version: v1.1.0 + version: v1.2.0-beta.1 spec: containers: - - image: gcr.io/google_containers/heapster:v1.1.0 + - image: gcr.io/google_containers/heapster:v1.2.0-beta.1 name: heapster resources: # keep request = limit to keep this container in guaranteed class @@ -58,7 +58,7 @@ spec: - name: ssl-certs mountPath: /etc/ssl/certs readOnly: true - - image: gcr.io/google_containers/heapster:v1.1.0 + - image: gcr.io/google_containers/heapster:v1.2.0-beta.1 name: eventer resources: # keep request = limit to keep this container in guaranteed class @@ -101,7 +101,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - --threshold=5 - - --deployment=heapster-v1.1.0 + - --deployment=heapster-v1.2.0-beta.1 - --container=heapster - --poll-period=300000 - --estimator=exponential @@ -130,7 +130,7 @@ spec: - --memory={{ base_eventer_memory }} - --extra-memory={{ eventer_memory_per_node }}Ki - --threshold=5 - - --deployment=heapster-v1.1.0 + - --deployment=heapster-v1.2.0-beta.1 - --container=eventer - --poll-period=300000 - --estimator=exponential diff --git a/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml b/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml index 50ca04c927d..699848ea619 100644 --- a/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/influxdb/heapster-controller.yaml @@ -20,26 +20,26 @@ apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.1.0 + name: heapster-v1.2.0-beta.1 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" - version: v1.1.0 + version: v1.2.0-beta.1 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.1.0 + version: v1.2.0-beta.1 template: metadata: labels: k8s-app: heapster - version: v1.1.0 + version: v1.2.0-beta.1 spec: containers: - - image: gcr.io/google_containers/heapster:v1.1.0 + - image: gcr.io/google_containers/heapster:v1.2.0-beta.1 name: heapster resources: # keep request = limit to keep this container in guaranteed class @@ -53,7 +53,7 @@ spec: - /heapster - --source=kubernetes.summary_api:'' - --sink=influxdb:http://monitoring-influxdb:8086 - - image: gcr.io/google_containers/heapster:v1.1.0 + - image: gcr.io/google_containers/heapster:v1.2.0-beta.1 name: eventer resources: # keep request = limit to keep this container in guaranteed class @@ -92,7 +92,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - --threshold=5 - - --deployment=heapster-v1.1.0 + - --deployment=heapster-v1.2.0-beta.1 - --container=heapster - --poll-period=300000 - --estimator=exponential @@ -121,7 +121,7 @@ spec: - --memory={{ base_eventer_memory }} - --extra-memory={{ eventer_memory_per_node }}Ki - --threshold=5 - - --deployment=heapster-v1.1.0 + - --deployment=heapster-v1.2.0-beta.1 - --container=eventer - --poll-period=300000 - --estimator=exponential diff --git a/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml b/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml index 32f6cf382b6..648ed17e4a8 100644 --- a/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml +++ b/cluster/addons/cluster-monitoring/standalone/heapster-controller.yaml @@ -16,26 +16,26 @@ apiVersion: extensions/v1beta1 kind: Deployment metadata: - name: heapster-v1.1.0 + name: heapster-v1.2.0-beta.1 namespace: kube-system labels: k8s-app: heapster kubernetes.io/cluster-service: "true" - version: v1.1.0 + version: v1.2.0-beta.1 spec: replicas: 1 selector: matchLabels: k8s-app: heapster - version: v1.1.0 + version: v1.2.0-beta.1 template: metadata: labels: k8s-app: heapster - version: v1.1.0 + version: v1.2.0-beta.1 spec: containers: - - image: gcr.io/google_containers/heapster:v1.1.0 + - image: gcr.io/google_containers/heapster:v1.2.0-beta.1 name: heapster resources: # keep request = limit to keep this container in guaranteed class @@ -73,7 +73,7 @@ spec: - --memory={{ base_metrics_memory }} - --extra-memory={{ metrics_memory_per_node }}Mi - --threshold=5 - - --deployment=heapster-v1.1.0 + - --deployment=heapster-v1.2.0-beta.1 - --container=heapster - --poll-period=300000 - --estimator=exponential 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..20f8a44730f 100644 --- a/pkg/kubectl/cmd/top_node_test.go +++ b/pkg/kubectl/cmd/top_node_test.go @@ -23,6 +23,7 @@ import ( "strings" "testing" + "k8s.io/heapster/metrics/apis/metrics/v1alpha1" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/client/restclient" @@ -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) diff --git a/vendor/k8s.io/heapster/metrics/api/v1/types/historical_types.go b/vendor/k8s.io/heapster/metrics/api/v1/types/historical_types.go new file mode 100644 index 00000000000..5da862e8ec3 --- /dev/null +++ b/vendor/k8s.io/heapster/metrics/api/v1/types/historical_types.go @@ -0,0 +1,49 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "time" +) + +// MetricValue is either a floating point value or an unsigned integer value +type MetricValue struct { + IntValue *int64 `json:"intValue,omitempty"` + FloatValue *float64 `json:"floatValue,omitempty"` +} + +// MetricAggregationBucket holds information about various aggregations across a single bucket of time +type MetricAggregationBucket struct { + Timestamp time.Time `json:"timestamp"` + Count *uint64 `json:"count,omitempty"` + + Average *MetricValue `json:"average,omitempty"` + Maximum *MetricValue `json:"maximum,omitempty"` + Minimum *MetricValue `json:"minimum,omitempty"` + Median *MetricValue `json:"median,omitempty"` + + Percentiles map[string]MetricValue `json:"percentiles,omitempty"` +} + +// MetricAggregationResult holds a series of MetricAggregationBuckets of a particular size +type MetricAggregationResult struct { + Buckets []MetricAggregationBucket `json:"buckets"` + BucketSize time.Duration `json:"bucketSize"` +} + +// MetricAggregationResultList is a list of MetricAggregationResults, each for a different object +type MetricAggregationResultList struct { + Items []MetricAggregationResult `json:"items"` +} diff --git a/vendor/k8s.io/heapster/metrics/apis/metrics/v1alpha1/types.go b/vendor/k8s.io/heapster/metrics/apis/metrics/v1alpha1/types.go index 03435be8a1c..430a01bd111 100644 --- a/vendor/k8s.io/heapster/metrics/apis/metrics/v1alpha1/types.go +++ b/vendor/k8s.io/heapster/metrics/apis/metrics/v1alpha1/types.go @@ -33,6 +33,17 @@ type NodeMetrics struct { Usage v1.ResourceList `json:"usage"` } +// NodeMetricsList is a list of NodeMetrics. +type NodeMetricsList struct { + unversioned.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds + unversioned.ListMeta `json:"metadata,omitempty"` + + // List of node metrics. + Items []NodeMetrics `json:"items"` +} + // resource usage metrics of a pod. type PodMetrics struct { unversioned.TypeMeta `json:",inline"` @@ -47,6 +58,17 @@ type PodMetrics struct { Containers []ContainerMetrics `json:"containers"` } +// PodMetricsList is a list of PodMetrics. +type PodMetricsList struct { + unversioned.TypeMeta `json:",inline"` + // Standard list metadata. + // More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds + unversioned.ListMeta `json:"metadata,omitempty"` + + // List of pod metrics. + Items []PodMetrics `json:"items"` +} + // resource usage metrics of a container. type ContainerMetrics struct { // Container name corresponding to the one from pod.spec.containers.