github.com/jonaz/heapster@v1.3.0-beta.0.0.20170208112634-cd3c15ca3d29/metrics/storage/podmetrics/reststorage.go (about)

     1  // Copyright 2016 Google Inc. All Rights Reserved.
     2  //
     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  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package app
    16  
    17  import (
    18  	"fmt"
    19  	"time"
    20  
    21  	"github.com/golang/glog"
    22  
    23  	"k8s.io/heapster/metrics/apis/metrics"
    24  	_ "k8s.io/heapster/metrics/apis/metrics/install"
    25  	"k8s.io/heapster/metrics/core"
    26  	metricsink "k8s.io/heapster/metrics/sinks/metric"
    27  	"k8s.io/heapster/metrics/storage/util"
    28  	"k8s.io/kubernetes/pkg/api"
    29  	"k8s.io/kubernetes/pkg/api/errors"
    30  	"k8s.io/kubernetes/pkg/api/unversioned"
    31  	"k8s.io/kubernetes/pkg/client/cache"
    32  	"k8s.io/kubernetes/pkg/labels"
    33  	"k8s.io/kubernetes/pkg/runtime"
    34  )
    35  
    36  type MetricStorage struct {
    37  	groupResource unversioned.GroupResource
    38  	metricSink    *metricsink.MetricSink
    39  	podLister     *cache.StoreToPodLister
    40  }
    41  
    42  func NewStorage(groupResource unversioned.GroupResource, metricSink *metricsink.MetricSink, podLister *cache.StoreToPodLister) *MetricStorage {
    43  	return &MetricStorage{
    44  		groupResource: groupResource,
    45  		metricSink:    metricSink,
    46  		podLister:     podLister,
    47  	}
    48  }
    49  
    50  // Storage interface
    51  func (m *MetricStorage) New() runtime.Object {
    52  	return &metrics.PodMetrics{}
    53  }
    54  
    55  // KindProvider interface
    56  func (m *MetricStorage) Kind() string {
    57  	return "PodMetrics"
    58  }
    59  
    60  // Lister interface
    61  func (m *MetricStorage) NewList() runtime.Object {
    62  	return &metrics.PodMetricsList{}
    63  }
    64  
    65  // Lister interface
    66  func (m *MetricStorage) List(ctx api.Context, options *api.ListOptions) (runtime.Object, error) {
    67  	labelSelector := labels.Everything()
    68  	if options != nil && options.LabelSelector != nil {
    69  		labelSelector = options.LabelSelector
    70  	}
    71  	namespace := api.NamespaceValue(ctx)
    72  	pods, err := m.podLister.Pods(namespace).List(labelSelector)
    73  	if err != nil {
    74  		errMsg := fmt.Errorf("Error while listing pods for selector %v: %v", labelSelector, err)
    75  		glog.Error(errMsg)
    76  		return &metrics.PodMetricsList{}, errMsg
    77  	}
    78  
    79  	res := metrics.PodMetricsList{}
    80  	for _, pod := range pods {
    81  		if podMetrics := m.getPodMetrics(pod); podMetrics != nil {
    82  			res.Items = append(res.Items, *podMetrics)
    83  		} else {
    84  			glog.Infof("No metrics for pod %s/%s", pod.Namespace, pod.Name)
    85  		}
    86  	}
    87  	return &res, nil
    88  }
    89  
    90  // Getter interface
    91  func (m *MetricStorage) Get(ctx api.Context, name string) (runtime.Object, error) {
    92  	namespace := api.NamespaceValue(ctx)
    93  
    94  	pod, err := m.podLister.Pods(namespace).Get(name)
    95  	if err != nil {
    96  		errMsg := fmt.Errorf("Error while getting pod %v: %v", name, err)
    97  		glog.Error(errMsg)
    98  		return &metrics.PodMetrics{}, errMsg
    99  	}
   100  	if pod == nil {
   101  		return &metrics.PodMetrics{}, errors.NewNotFound(api.Resource("Pod"), fmt.Sprintf("%v/%v", namespace, name))
   102  	}
   103  
   104  	podMetrics := m.getPodMetrics(pod)
   105  	if podMetrics == nil {
   106  		return &metrics.PodMetrics{}, errors.NewNotFound(m.groupResource, fmt.Sprintf("%v/%v", namespace, name))
   107  	}
   108  	return podMetrics, nil
   109  }
   110  
   111  func (m *MetricStorage) getPodMetrics(pod *api.Pod) *metrics.PodMetrics {
   112  	batch := m.metricSink.GetLatestDataBatch()
   113  	if batch == nil {
   114  		return nil
   115  	}
   116  
   117  	res := &metrics.PodMetrics{
   118  		ObjectMeta: api.ObjectMeta{
   119  			Name:              pod.Name,
   120  			Namespace:         pod.Namespace,
   121  			CreationTimestamp: unversioned.NewTime(time.Now()),
   122  		},
   123  		Timestamp:  unversioned.NewTime(batch.Timestamp),
   124  		Window:     unversioned.Duration{Duration: time.Minute},
   125  		Containers: make([]metrics.ContainerMetrics, 0),
   126  	}
   127  
   128  	for _, c := range pod.Spec.Containers {
   129  		ms, found := batch.MetricSets[core.PodContainerKey(pod.Namespace, pod.Name, c.Name)]
   130  		if !found {
   131  			glog.Infof("No metrics for container %s in pod %s/%s", c.Name, pod.Namespace, pod.Name)
   132  			return nil
   133  		}
   134  		usage, err := util.ParseResourceList(ms)
   135  		if err != nil {
   136  			return nil
   137  		}
   138  		res.Containers = append(res.Containers, metrics.ContainerMetrics{Name: c.Name, Usage: usage})
   139  	}
   140  
   141  	return res
   142  }