func (a *Api) exportMetricsSchema(request *restful.Request, response *restful.Response) { result := TimeseriesSchema{} for _, label := range sinksApi.CommonLabels() { result.CommonLabels = append(result.CommonLabels, LabelDescriptor{ Key: label.Key, Description: label.Description, }) } for _, label := range sinksApi.PodLabels() { result.PodLabels = append(result.PodLabels, LabelDescriptor{ Key: label.Key, Description: label.Description, }) } for _, metric := range sinksApi.SupportedStatMetrics() { md := MetricDescriptor{ Name: metric.Name, Description: metric.Description, Type: metric.Type.String(), ValueType: metric.ValueType.String(), Units: metric.Units.String(), } for _, label := range metric.Labels { md.Labels = append(md.Labels, LabelDescriptor{ Key: label.Key, Description: label.Description, }) } result.Metrics = append(result.Metrics, md) } response.WriteEntity(result) }
func runHeapsterMetricsTest(fm kubeFramework, svc *kube_api.Service) error { expectedPods, err := fm.GetRunningPodNames() if err != nil { return err } expectedNodes, err := fm.GetNodes() if err != nil { return err } timeseries, err := getTimeseries(fm, svc) if err != nil { return err } if len(timeseries) == 0 { return fmt.Errorf("expected non zero timeseries") } schema, err := getSchema(fm, svc) if err != nil { return err } // Build a map of metric names to metric descriptors. mdMap := map[string]*api_v1.MetricDescriptor{} for idx := range schema.Metrics { mdMap[schema.Metrics[idx].Name] = &schema.Metrics[idx] } actualPods := map[string]bool{} actualNodes := map[string]bool{} actualSystemContainers := map[string]map[string]struct{}{} for _, ts := range timeseries { // Verify the relevant labels are present. // All common labels must be present. for _, label := range sink_api.CommonLabels() { if label == sink_api.LabelContainerBaseImage && !isContainerBaseImageExpected(ts) { continue } _, exists := ts.Labels[label.Key] if !exists { return fmt.Errorf("timeseries: %v does not contain common label: %v", ts, label) } } podName, podMetric := ts.Labels[sink_api.LabelPodName.Key] if podMetric { for _, label := range sink_api.PodLabels() { _, exists := ts.Labels[label.Key] if !exists { return fmt.Errorf("timeseries: %v does not contain pod label: %v", ts, label) } } } if podMetric { actualPods[podName] = true } else { if cName, ok := ts.Labels[sink_api.LabelContainerName.Key]; ok { hostname, ok := ts.Labels[sink_api.LabelHostname.Key] if !ok { return fmt.Errorf("hostname label missing on container %+v", ts) } if cName == cache.NodeContainerName { actualNodes[hostname] = true } if _, exists := expectedSystemContainers[cName]; exists { if actualSystemContainers[cName] == nil { actualSystemContainers[cName] = map[string]struct{}{} } actualSystemContainers[cName][hostname] = struct{}{} } } else { return fmt.Errorf("container_name label missing on timeseries - %v", ts) } } for metricName, points := range ts.Metrics { md, exists := mdMap[metricName] if !exists { return fmt.Errorf("unexpected metric %q", metricName) } for _, point := range points { for _, label := range md.Labels { _, exists := point.Labels[label.Key] if !exists { return fmt.Errorf("metric %q point %v does not contain metric label: %v", metricName, point, label) } } } } } // Validate that system containers are running on all the nodes. // This test could fail if one of the containers was down while the metrics sample was collected. for cName, hosts := range actualSystemContainers { for _, host := range expectedNodes { if _, ok := hosts[host]; !ok { return fmt.Errorf("System container %q not found on host: %q - %v", cName, host, actualSystemContainers) } } } if err := expectedItemsExist(expectedPods, actualPods); err != nil { return fmt.Errorf("expected pods don't exist %v.\nExpected: %v\nActual:%v", err, expectedPods, actualPods) } if err := expectedItemsExist(expectedNodes, actualNodes); err != nil { return fmt.Errorf("expected nodes don't exist %v.\nExpected: %v\nActual:%v", err, expectedNodes, actualNodes) } return nil }