metrics_client.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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 metricsutil
  14. import (
  15. "encoding/json"
  16. "errors"
  17. "fmt"
  18. metrics_api "k8s.io/heapster/metrics/apis/metrics/v1alpha1"
  19. "k8s.io/kubernetes/pkg/api"
  20. "k8s.io/kubernetes/pkg/api/unversioned"
  21. "k8s.io/kubernetes/pkg/api/validation"
  22. client "k8s.io/kubernetes/pkg/client/unversioned"
  23. "k8s.io/kubernetes/pkg/labels"
  24. )
  25. const (
  26. DefaultHeapsterNamespace = "kube-system"
  27. DefaultHeapsterScheme = "http"
  28. DefaultHeapsterService = "heapster"
  29. DefaultHeapsterPort = "" // use the first exposed port on the service
  30. )
  31. var (
  32. prefix = "/apis"
  33. groupVersion = fmt.Sprintf("%s/%s", metricsGv.Group, metricsGv.Version)
  34. metricsRoot = fmt.Sprintf("%s/%s", prefix, groupVersion)
  35. // TODO: get this from metrics api once it's finished
  36. metricsGv = unversioned.GroupVersion{Group: "metrics", Version: "v1alpha1"}
  37. )
  38. type HeapsterMetricsClient struct {
  39. *client.Client
  40. HeapsterNamespace string
  41. HeapsterScheme string
  42. HeapsterService string
  43. HeapsterPort string
  44. }
  45. func NewHeapsterMetricsClient(client *client.Client, namespace, scheme, service, port string) *HeapsterMetricsClient {
  46. return &HeapsterMetricsClient{
  47. Client: client,
  48. HeapsterNamespace: namespace,
  49. HeapsterScheme: scheme,
  50. HeapsterService: service,
  51. HeapsterPort: port,
  52. }
  53. }
  54. func DefaultHeapsterMetricsClient(client *client.Client) *HeapsterMetricsClient {
  55. return NewHeapsterMetricsClient(client, DefaultHeapsterNamespace, DefaultHeapsterScheme, DefaultHeapsterService, DefaultHeapsterPort)
  56. }
  57. func podMetricsUrl(namespace string, name string) (string, error) {
  58. if namespace == api.NamespaceAll {
  59. return fmt.Sprintf("%s/pods", metricsRoot), nil
  60. }
  61. errs := validation.ValidateNamespaceName(namespace, false)
  62. if len(errs) > 0 {
  63. message := fmt.Sprintf("invalid namespace: %s - %v", namespace, errs)
  64. return "", errors.New(message)
  65. }
  66. if len(name) > 0 {
  67. errs = validation.ValidatePodName(name, false)
  68. if len(errs) > 0 {
  69. message := fmt.Sprintf("invalid pod name: %s - %v", name, errs)
  70. return "", errors.New(message)
  71. }
  72. }
  73. return fmt.Sprintf("%s/namespaces/%s/pods/%s", metricsRoot, namespace, name), nil
  74. }
  75. func nodeMetricsUrl(name string) (string, error) {
  76. if len(name) > 0 {
  77. errs := validation.ValidateNodeName(name, false)
  78. if len(errs) > 0 {
  79. message := fmt.Sprintf("invalid node name: %s - %v", name, errs)
  80. return "", errors.New(message)
  81. }
  82. }
  83. return fmt.Sprintf("%s/nodes/%s", metricsRoot, name), nil
  84. }
  85. func (cli *HeapsterMetricsClient) GetNodeMetrics(nodeName string, selector labels.Selector) ([]metrics_api.NodeMetrics, error) {
  86. params := map[string]string{"labelSelector": selector.String()}
  87. path, err := nodeMetricsUrl(nodeName)
  88. if err != nil {
  89. return []metrics_api.NodeMetrics{}, err
  90. }
  91. resultRaw, err := GetHeapsterMetrics(cli, path, params)
  92. if err != nil {
  93. return []metrics_api.NodeMetrics{}, err
  94. }
  95. metrics := make([]metrics_api.NodeMetrics, 0)
  96. if len(nodeName) == 0 {
  97. metricsList := metrics_api.NodeMetricsList{}
  98. err = json.Unmarshal(resultRaw, &metricsList)
  99. if err != nil {
  100. return []metrics_api.NodeMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err)
  101. }
  102. metrics = append(metrics, metricsList.Items...)
  103. } else {
  104. var singleMetric metrics_api.NodeMetrics
  105. err = json.Unmarshal(resultRaw, &singleMetric)
  106. if err != nil {
  107. return []metrics_api.NodeMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err)
  108. }
  109. metrics = append(metrics, singleMetric)
  110. }
  111. return metrics, nil
  112. }
  113. func (cli *HeapsterMetricsClient) GetPodMetrics(namespace string, podName string, allNamespaces bool, selector labels.Selector) ([]metrics_api.PodMetrics, error) {
  114. if allNamespaces {
  115. namespace = api.NamespaceAll
  116. }
  117. path, err := podMetricsUrl(namespace, podName)
  118. if err != nil {
  119. return []metrics_api.PodMetrics{}, err
  120. }
  121. params := map[string]string{"labelSelector": selector.String()}
  122. allMetrics := make([]metrics_api.PodMetrics, 0)
  123. resultRaw, err := GetHeapsterMetrics(cli, path, params)
  124. if err != nil {
  125. return []metrics_api.PodMetrics{}, err
  126. }
  127. if len(podName) == 0 {
  128. metrics := metrics_api.PodMetricsList{}
  129. err = json.Unmarshal(resultRaw, &metrics)
  130. if err != nil {
  131. return []metrics_api.PodMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err)
  132. }
  133. allMetrics = append(allMetrics, metrics.Items...)
  134. } else {
  135. var singleMetric metrics_api.PodMetrics
  136. err = json.Unmarshal(resultRaw, &singleMetric)
  137. if err != nil {
  138. return []metrics_api.PodMetrics{}, fmt.Errorf("failed to unmarshall heapster response: %v", err)
  139. }
  140. allMetrics = append(allMetrics, singleMetric)
  141. }
  142. return allMetrics, nil
  143. }
  144. func GetHeapsterMetrics(cli *HeapsterMetricsClient, path string, params map[string]string) ([]byte, error) {
  145. return cli.Services(cli.HeapsterNamespace).
  146. ProxyGet(cli.HeapsterScheme, cli.HeapsterService, cli.HeapsterPort, path, params).
  147. DoRaw()
  148. }