Merge pull request #30993 from mksalawa/bump_heapster_version

Automatic merge from submit-queue

Bump heapster version

Bump heapster version to v1.2.0-beta.1.
Migrate metrics tests and HPA to use List objects introduced in the new version.
This commit is contained in:
Kubernetes Submit Queue 2016-08-19 19:36:53 -07:00 committed by GitHub
commit c39f0eec4a
14 changed files with 261 additions and 149 deletions

8
Godeps/Godeps.json generated
View File

@ -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"
}
]
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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),
},
},
},
},

View File

@ -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)

View File

@ -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"`
}

View File

@ -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.