mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-01-05 23:47:50 +00:00
kubectl: Use metrics-server for kubectl top commands
This commit is contained in:
@@ -19,6 +19,7 @@ package cmd
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -26,9 +27,13 @@ import (
|
||||
"net/url"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/rest/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||
"k8s.io/metrics/pkg/apis/metrics/v1alpha1"
|
||||
metricsv1alpha1api "k8s.io/metrics/pkg/apis/metrics/v1alpha1"
|
||||
metricsv1beta1api "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||
metricsfake "k8s.io/metrics/pkg/client/clientset_generated/clientset/fake"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -38,7 +43,7 @@ const (
|
||||
|
||||
func TestTopNodeAllMetrics(t *testing.T) {
|
||||
initTestErrorHandler(t)
|
||||
metrics, nodes := testNodeMetricsData()
|
||||
metrics, nodes := testNodeV1alpha1MetricsData()
|
||||
expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", baseMetricsAddress, metricsApiVersion)
|
||||
expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion)
|
||||
|
||||
@@ -48,6 +53,10 @@ func TestTopNodeAllMetrics(t *testing.T) {
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
switch p, m := req.URL.Path, req.Method; {
|
||||
case p == "/api":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
|
||||
case p == "/apis":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
|
||||
case p == expectedMetricsPath && m == "GET":
|
||||
body, err := marshallBody(metrics)
|
||||
if err != nil {
|
||||
@@ -83,7 +92,7 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) {
|
||||
customBaseMetricsAddress := customBaseHeapsterServiceAddress + "/apis/metrics"
|
||||
|
||||
initTestErrorHandler(t)
|
||||
metrics, nodes := testNodeMetricsData()
|
||||
metrics, nodes := testNodeV1alpha1MetricsData()
|
||||
expectedMetricsPath := fmt.Sprintf("%s/%s/nodes", customBaseMetricsAddress, metricsApiVersion)
|
||||
expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion)
|
||||
|
||||
@@ -93,6 +102,10 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) {
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
switch p, m := req.URL.Path, req.Method; {
|
||||
case p == "/api":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
|
||||
case p == "/apis":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
|
||||
case p == expectedMetricsPath && m == "GET":
|
||||
body, err := marshallBody(metrics)
|
||||
if err != nil {
|
||||
@@ -132,10 +145,10 @@ func TestTopNodeAllMetricsCustomDefaults(t *testing.T) {
|
||||
|
||||
func TestTopNodeWithNameMetrics(t *testing.T) {
|
||||
initTestErrorHandler(t)
|
||||
metrics, nodes := testNodeMetricsData()
|
||||
metrics, nodes := testNodeV1alpha1MetricsData()
|
||||
expectedMetrics := metrics.Items[0]
|
||||
expectedNode := nodes.Items[0]
|
||||
nonExpectedMetrics := v1alpha1.NodeMetricsList{
|
||||
nonExpectedMetrics := metricsv1alpha1api.NodeMetricsList{
|
||||
ListMeta: metrics.ListMeta,
|
||||
Items: metrics.Items[1:],
|
||||
}
|
||||
@@ -148,6 +161,10 @@ func TestTopNodeWithNameMetrics(t *testing.T) {
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
switch p, m := req.URL.Path, req.Method; {
|
||||
case p == "/api":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
|
||||
case p == "/apis":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
|
||||
case p == expectedPath && m == "GET":
|
||||
body, err := marshallBody(expectedMetrics)
|
||||
if err != nil {
|
||||
@@ -183,8 +200,8 @@ func TestTopNodeWithNameMetrics(t *testing.T) {
|
||||
|
||||
func TestTopNodeWithLabelSelectorMetrics(t *testing.T) {
|
||||
initTestErrorHandler(t)
|
||||
metrics, nodes := testNodeMetricsData()
|
||||
expectedMetrics := v1alpha1.NodeMetricsList{
|
||||
metrics, nodes := testNodeV1alpha1MetricsData()
|
||||
expectedMetrics := metricsv1alpha1api.NodeMetricsList{
|
||||
ListMeta: metrics.ListMeta,
|
||||
Items: metrics.Items[0:1],
|
||||
}
|
||||
@@ -192,7 +209,7 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) {
|
||||
ListMeta: nodes.ListMeta,
|
||||
Items: nodes.Items[0:1],
|
||||
}
|
||||
nonExpectedMetrics := v1alpha1.NodeMetricsList{
|
||||
nonExpectedMetrics := metricsv1alpha1api.NodeMetricsList{
|
||||
ListMeta: metrics.ListMeta,
|
||||
Items: metrics.Items[1:],
|
||||
}
|
||||
@@ -207,6 +224,10 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) {
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; {
|
||||
case p == "/api":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
|
||||
case p == "/apis":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbody)))}, nil
|
||||
case p == expectedPath && m == "GET" && q == expectedQuery:
|
||||
body, err := marshallBody(expectedMetrics)
|
||||
if err != nil {
|
||||
@@ -242,3 +263,164 @@ func TestTopNodeWithLabelSelectorMetrics(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTopNodeAllMetricsFromMetricsServer(t *testing.T) {
|
||||
initTestErrorHandler(t)
|
||||
expectedMetrics, nodes := testNodeV1beta1MetricsData()
|
||||
expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion)
|
||||
|
||||
f, tf, codec, ns := cmdtesting.NewAPIFactory()
|
||||
tf.Printer = &testPrinter{}
|
||||
tf.Client = &fake.RESTClient{
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
switch p, m := req.URL.Path, req.Method; {
|
||||
case p == "/api":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
|
||||
case p == "/apis":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil
|
||||
case p == expectedNodePath && m == "GET":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, nodes)}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected request: %#v\nGot URL: %#v\n", req, req.URL)
|
||||
return nil, nil
|
||||
}
|
||||
}),
|
||||
}
|
||||
fakemetricsClientset := &metricsfake.Clientset{}
|
||||
fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, expectedMetrics, nil
|
||||
})
|
||||
tf.MetricsClientSet = fakemetricsClientset
|
||||
tf.Namespace = "test"
|
||||
tf.ClientConfig = defaultClientConfig()
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := NewCmdTopNode(f, nil, buf)
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
// Check the presence of node names in the output.
|
||||
result := buf.String()
|
||||
for _, m := range expectedMetrics.Items {
|
||||
if !strings.Contains(result, m.Name) {
|
||||
t.Errorf("missing metrics for %s: \n%s", m.Name, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTopNodeWithNameMetricsFromMetricsServer(t *testing.T) {
|
||||
initTestErrorHandler(t)
|
||||
metrics, nodes := testNodeV1beta1MetricsData()
|
||||
expectedMetrics := metrics.Items[0]
|
||||
expectedNode := nodes.Items[0]
|
||||
nonExpectedMetrics := metricsv1beta1api.NodeMetricsList{
|
||||
ListMeta: metrics.ListMeta,
|
||||
Items: metrics.Items[1:],
|
||||
}
|
||||
expectedNodePath := fmt.Sprintf("/%s/%s/nodes/%s", apiPrefix, apiVersion, expectedMetrics.Name)
|
||||
|
||||
f, tf, codec, ns := cmdtesting.NewAPIFactory()
|
||||
tf.Printer = &testPrinter{}
|
||||
tf.Client = &fake.RESTClient{
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
switch p, m := req.URL.Path, req.Method; {
|
||||
case p == "/api":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
|
||||
case p == "/apis":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil
|
||||
case p == expectedNodePath && m == "GET":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &expectedNode)}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected request: %#v\nGot URL: %#v\n", req, req.URL)
|
||||
return nil, nil
|
||||
}
|
||||
}),
|
||||
}
|
||||
fakemetricsClientset := &metricsfake.Clientset{}
|
||||
fakemetricsClientset.AddReactor("get", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, &expectedMetrics, nil
|
||||
})
|
||||
tf.MetricsClientSet = fakemetricsClientset
|
||||
tf.Namespace = "test"
|
||||
tf.ClientConfig = defaultClientConfig()
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := NewCmdTopNode(f, nil, buf)
|
||||
cmd.Run(cmd, []string{expectedMetrics.Name})
|
||||
|
||||
// Check the presence of node names in the output.
|
||||
result := buf.String()
|
||||
if !strings.Contains(result, expectedMetrics.Name) {
|
||||
t.Errorf("missing metrics for %s: \n%s", expectedMetrics.Name, result)
|
||||
}
|
||||
for _, m := range nonExpectedMetrics.Items {
|
||||
if strings.Contains(result, m.Name) {
|
||||
t.Errorf("unexpected metrics for %s: \n%s", m.Name, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTopNodeWithLabelSelectorMetricsFromMetricsServer(t *testing.T) {
|
||||
initTestErrorHandler(t)
|
||||
metrics, nodes := testNodeV1beta1MetricsData()
|
||||
expectedMetrics := &metricsv1beta1api.NodeMetricsList{
|
||||
ListMeta: metrics.ListMeta,
|
||||
Items: metrics.Items[0:1],
|
||||
}
|
||||
expectedNodes := v1.NodeList{
|
||||
ListMeta: nodes.ListMeta,
|
||||
Items: nodes.Items[0:1],
|
||||
}
|
||||
nonExpectedMetrics := &metricsv1beta1api.NodeMetricsList{
|
||||
ListMeta: metrics.ListMeta,
|
||||
Items: metrics.Items[1:],
|
||||
}
|
||||
label := "key=value"
|
||||
expectedNodePath := fmt.Sprintf("/%s/%s/nodes", apiPrefix, apiVersion)
|
||||
|
||||
f, tf, codec, ns := cmdtesting.NewAPIFactory()
|
||||
tf.Printer = &testPrinter{}
|
||||
tf.Client = &fake.RESTClient{
|
||||
NegotiatedSerializer: ns,
|
||||
Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||
switch p, m, _ := req.URL.Path, req.Method, req.URL.RawQuery; {
|
||||
case p == "/api":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apibody)))}, nil
|
||||
case p == "/apis":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: ioutil.NopCloser(bytes.NewReader([]byte(apisbodyWithMetrics)))}, nil
|
||||
case p == expectedNodePath && m == "GET":
|
||||
return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &expectedNodes)}, nil
|
||||
default:
|
||||
t.Fatalf("unexpected request: %#v\nGot URL: %#v\n", req, req.URL)
|
||||
return nil, nil
|
||||
}
|
||||
}),
|
||||
}
|
||||
|
||||
fakemetricsClientset := &metricsfake.Clientset{}
|
||||
fakemetricsClientset.AddReactor("list", "nodes", func(action core.Action) (handled bool, ret runtime.Object, err error) {
|
||||
return true, expectedMetrics, nil
|
||||
})
|
||||
tf.MetricsClientSet = fakemetricsClientset
|
||||
tf.Namespace = "test"
|
||||
tf.ClientConfig = defaultClientConfig()
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := NewCmdTopNode(f, nil, buf)
|
||||
cmd.Flags().Set("selector", label)
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
// Check the presence of node names in the output.
|
||||
result := buf.String()
|
||||
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.Items {
|
||||
if strings.Contains(result, m.Name) {
|
||||
t.Errorf("unexpected metrics for %s: \n%s", m.Name, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user