top_pod_test.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package cmd
  14. import (
  15. "bytes"
  16. "fmt"
  17. "net/http"
  18. "strings"
  19. "testing"
  20. metrics_api "k8s.io/heapster/metrics/apis/metrics/v1alpha1"
  21. "k8s.io/kubernetes/pkg/api/unversioned"
  22. "k8s.io/kubernetes/pkg/client/restclient"
  23. "k8s.io/kubernetes/pkg/client/unversioned/fake"
  24. "net/url"
  25. )
  26. func TestTopPodAllNamespacesMetrics(t *testing.T) {
  27. initTestErrorHandler(t)
  28. metrics := testPodMetricsData()
  29. firstTestNamespace := "testnamespace"
  30. secondTestNamespace := "secondtestns"
  31. thirdTestNamespace := "thirdtestns"
  32. metrics.Items[0].Namespace = firstTestNamespace
  33. metrics.Items[1].Namespace = secondTestNamespace
  34. metrics.Items[2].Namespace = thirdTestNamespace
  35. expectedPath := fmt.Sprintf("%s/%s/pods", baseMetricsAddress, metricsApiVersion)
  36. f, tf, _, ns := NewAPIFactory()
  37. tf.Printer = &testPrinter{}
  38. tf.Client = &fake.RESTClient{
  39. NegotiatedSerializer: ns,
  40. Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
  41. switch p, m := req.URL.Path, req.Method; {
  42. case p == expectedPath && m == "GET":
  43. body, err := marshallBody(metrics)
  44. if err != nil {
  45. t.Errorf("unexpected error: %v", err)
  46. }
  47. return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil
  48. default:
  49. t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath)
  50. return nil, nil
  51. }
  52. }),
  53. }
  54. tf.Namespace = firstTestNamespace
  55. tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}}
  56. buf := bytes.NewBuffer([]byte{})
  57. cmd := NewCmdTopPod(f, buf)
  58. cmd.Flags().Set("all-namespaces", "true")
  59. cmd.Run(cmd, []string{})
  60. // Check the presence of pod names and namespaces in the output.
  61. result := buf.String()
  62. for _, m := range metrics.Items {
  63. if !strings.Contains(result, m.Name) {
  64. t.Errorf("missing metrics for %s: \n%s", m.Name, result)
  65. }
  66. if !strings.Contains(result, m.Namespace) {
  67. t.Errorf("missing metrics for %s/%s: \n%s", m.Namespace, m.Name, result)
  68. }
  69. }
  70. }
  71. func TestTopPodAllInNamespaceMetrics(t *testing.T) {
  72. initTestErrorHandler(t)
  73. metrics := testPodMetricsData()
  74. testNamespace := "testnamespace"
  75. nonTestNamespace := "anothernamespace"
  76. expectedMetrics := metrics_api.PodMetricsList{
  77. ListMeta: metrics.ListMeta,
  78. Items: metrics.Items[0:2],
  79. }
  80. for _, m := range expectedMetrics.Items {
  81. m.Namespace = testNamespace
  82. }
  83. nonExpectedMetrics := metrics_api.PodMetricsList{
  84. ListMeta: metrics.ListMeta,
  85. Items: metrics.Items[2:],
  86. }
  87. for _, m := range nonExpectedMetrics.Items {
  88. m.Namespace = nonTestNamespace
  89. }
  90. expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods", baseMetricsAddress, metricsApiVersion, testNamespace)
  91. f, tf, _, ns := NewAPIFactory()
  92. tf.Printer = &testPrinter{}
  93. tf.Client = &fake.RESTClient{
  94. NegotiatedSerializer: ns,
  95. Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
  96. switch p, m := req.URL.Path, req.Method; {
  97. case p == expectedPath && m == "GET":
  98. body, err := marshallBody(expectedMetrics)
  99. if err != nil {
  100. t.Errorf("unexpected error: %v", err)
  101. }
  102. return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil
  103. default:
  104. t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath)
  105. return nil, nil
  106. }
  107. }),
  108. }
  109. tf.Namespace = testNamespace
  110. tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}}
  111. buf := bytes.NewBuffer([]byte{})
  112. cmd := NewCmdTopPod(f, buf)
  113. cmd.Run(cmd, []string{})
  114. // Check the presence of pod names in the output.
  115. result := buf.String()
  116. for _, m := range expectedMetrics.Items {
  117. if !strings.Contains(result, m.Name) {
  118. t.Errorf("missing metrics for %s: \n%s", m.Name, result)
  119. }
  120. }
  121. for _, m := range nonExpectedMetrics.Items {
  122. if strings.Contains(result, m.Name) {
  123. t.Errorf("unexpected metrics for %s: \n%s", m.Name, result)
  124. }
  125. }
  126. }
  127. func TestTopPodWithNameMetrics(t *testing.T) {
  128. initTestErrorHandler(t)
  129. metrics := testPodMetricsData()
  130. expectedMetrics := metrics.Items[0]
  131. nonExpectedMetrics := metrics_api.PodMetricsList{
  132. ListMeta: metrics.ListMeta,
  133. Items: metrics.Items[1:],
  134. }
  135. testNamespace := "testnamespace"
  136. expectedMetrics.Namespace = testNamespace
  137. expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods/%s", baseMetricsAddress, metricsApiVersion, testNamespace, expectedMetrics.Name)
  138. f, tf, _, ns := NewAPIFactory()
  139. tf.Printer = &testPrinter{}
  140. tf.Client = &fake.RESTClient{
  141. NegotiatedSerializer: ns,
  142. Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
  143. switch p, m := req.URL.Path, req.Method; {
  144. case p == expectedPath && m == "GET":
  145. body, err := marshallBody(expectedMetrics)
  146. if err != nil {
  147. t.Errorf("unexpected error: %v", err)
  148. }
  149. return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil
  150. default:
  151. t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath)
  152. return nil, nil
  153. }
  154. }),
  155. }
  156. tf.Namespace = testNamespace
  157. tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}}
  158. buf := bytes.NewBuffer([]byte{})
  159. cmd := NewCmdTopPod(f, buf)
  160. cmd.Run(cmd, []string{expectedMetrics.Name})
  161. // Check the presence of pod names in the output.
  162. result := buf.String()
  163. if !strings.Contains(result, expectedMetrics.Name) {
  164. t.Errorf("missing metrics for %s: \n%s", expectedMetrics.Name, result)
  165. }
  166. for _, m := range nonExpectedMetrics.Items {
  167. if strings.Contains(result, m.Name) {
  168. t.Errorf("unexpected metrics for %s: \n%s", m.Name, result)
  169. }
  170. }
  171. }
  172. func TestTopPodWithLabelSelectorMetrics(t *testing.T) {
  173. initTestErrorHandler(t)
  174. metrics := testPodMetricsData()
  175. expectedMetrics := metrics_api.PodMetricsList{
  176. ListMeta: metrics.ListMeta,
  177. Items: metrics.Items[0:2],
  178. }
  179. nonExpectedMetrics := metrics_api.PodMetricsList{
  180. ListMeta: metrics.ListMeta,
  181. Items: metrics.Items[2:],
  182. }
  183. label := "key=value"
  184. testNamespace := "testnamespace"
  185. expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods", baseMetricsAddress, metricsApiVersion, testNamespace)
  186. expectedQuery := fmt.Sprintf("labelSelector=%s", url.QueryEscape(label))
  187. f, tf, _, ns := NewAPIFactory()
  188. tf.Printer = &testPrinter{}
  189. tf.Client = &fake.RESTClient{
  190. NegotiatedSerializer: ns,
  191. Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
  192. switch p, m, q := req.URL.Path, req.Method, req.URL.RawQuery; {
  193. case p == expectedPath && m == "GET" && q == expectedQuery:
  194. body, err := marshallBody(expectedMetrics)
  195. if err != nil {
  196. t.Errorf("unexpected error: %v", err)
  197. }
  198. return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil
  199. default:
  200. t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath)
  201. return nil, nil
  202. }
  203. }),
  204. }
  205. tf.Namespace = testNamespace
  206. tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}}
  207. buf := bytes.NewBuffer([]byte{})
  208. cmd := NewCmdTopPod(f, buf)
  209. cmd.Flags().Set("selector", label)
  210. cmd.Run(cmd, []string{})
  211. // Check the presence of pod names in the output.
  212. result := buf.String()
  213. for _, m := range expectedMetrics.Items {
  214. if !strings.Contains(result, m.Name) {
  215. t.Errorf("missing metrics for %s: \n%s", m.Name, result)
  216. }
  217. }
  218. for _, m := range nonExpectedMetrics.Items {
  219. if strings.Contains(result, m.Name) {
  220. t.Errorf("unexpected metrics for %s: \n%s", m.Name, result)
  221. }
  222. }
  223. }
  224. func TestTopPodWithContainersMetrics(t *testing.T) {
  225. initTestErrorHandler(t)
  226. metrics := testPodMetricsData()
  227. expectedMetrics := metrics.Items[0]
  228. nonExpectedMetrics := metrics_api.PodMetricsList{
  229. ListMeta: metrics.ListMeta,
  230. Items: metrics.Items[1:],
  231. }
  232. testNamespace := "testnamespace"
  233. expectedMetrics.Namespace = testNamespace
  234. expectedPath := fmt.Sprintf("%s/%s/namespaces/%s/pods/%s", baseMetricsAddress, metricsApiVersion, testNamespace, expectedMetrics.Name)
  235. f, tf, _, ns := NewAPIFactory()
  236. tf.Printer = &testPrinter{}
  237. tf.Client = &fake.RESTClient{
  238. NegotiatedSerializer: ns,
  239. Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
  240. switch p, m := req.URL.Path, req.Method; {
  241. case p == expectedPath && m == "GET":
  242. body, err := marshallBody(expectedMetrics)
  243. if err != nil {
  244. t.Errorf("unexpected error: %v", err)
  245. }
  246. return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: body}, nil
  247. default:
  248. t.Fatalf("unexpected request: %#v\nGot URL: %#v\nExpected path: %#v", req, req.URL, expectedPath)
  249. return nil, nil
  250. }
  251. }),
  252. }
  253. tf.Namespace = testNamespace
  254. tf.ClientConfig = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &unversioned.GroupVersion{Version: "v1"}}}
  255. buf := bytes.NewBuffer([]byte{})
  256. cmd := NewCmdTopPod(f, buf)
  257. cmd.Flags().Set("containers", "true")
  258. cmd.Run(cmd, []string{expectedMetrics.Name})
  259. // Check the presence of pod names in the output.
  260. result := buf.String()
  261. if !strings.Contains(result, expectedMetrics.Name) {
  262. t.Errorf("missing metrics for %s: \n%s", expectedMetrics.Name, result)
  263. }
  264. for _, m := range expectedMetrics.Containers {
  265. if !strings.Contains(result, m.Name) {
  266. t.Errorf("missing metrics for container %s: \n%s", m.Name, result)
  267. }
  268. }
  269. for _, m := range nonExpectedMetrics.Items {
  270. if strings.Contains(result, m.Name) {
  271. t.Errorf("unexpected metrics for %s: \n%s", m.Name, result)
  272. }
  273. }
  274. }