github.com/kiali/kiali@v1.84.0/business/health_test.go (about)

     1  package business
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  	"time"
     7  
     8  	osproject_v1 "github.com/openshift/api/project/v1"
     9  	"github.com/prometheus/common/model"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/mock"
    12  	"github.com/stretchr/testify/require"
    13  	apps_v1 "k8s.io/api/apps/v1"
    14  	core_v1 "k8s.io/api/core/v1"
    15  	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    16  	"k8s.io/apimachinery/pkg/runtime"
    17  
    18  	"github.com/kiali/kiali/config"
    19  	"github.com/kiali/kiali/kubernetes"
    20  	"github.com/kiali/kiali/kubernetes/cache"
    21  	"github.com/kiali/kiali/kubernetes/kubetest"
    22  	"github.com/kiali/kiali/models"
    23  	"github.com/kiali/kiali/prometheus/prometheustest"
    24  )
    25  
    26  var emptyResult = map[string]map[string]float64{}
    27  
    28  func TestGetServiceHealth(t *testing.T) {
    29  	assert := assert.New(t)
    30  
    31  	conf := config.NewConfig()
    32  	config.Set(conf)
    33  
    34  	k8s := kubetest.NewFakeK8sClient(
    35  		&osproject_v1.Project{ObjectMeta: meta_v1.ObjectMeta{Name: "ns"}},
    36  		&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "ns"}},
    37  	)
    38  	k8s.OpenShift = true
    39  	clients := make(map[string]kubernetes.ClientInterface)
    40  	clients[conf.KubernetesConfig.ClusterName] = k8s
    41  
    42  	prom := new(prometheustest.PromClientMock)
    43  
    44  	queryTime := time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC)
    45  	prom.MockServiceRequestRates("ns", conf.KubernetesConfig.ClusterName, "httpbin", serviceRates)
    46  
    47  	hs := HealthService{prom: prom, businessLayer: NewWithBackends(clients, clients, prom, nil), userClients: clients}
    48  
    49  	mockSvc := models.Service{}
    50  	mockSvc.Name = "httpbin"
    51  
    52  	health, _ := hs.GetServiceHealth(context.TODO(), "ns", conf.KubernetesConfig.ClusterName, "httpbin", "1m", queryTime, &mockSvc)
    53  
    54  	prom.AssertNumberOfCalls(t, "GetServiceRequestRates", 1)
    55  	result := map[string]map[string]float64{
    56  		"http": {
    57  			"200": 14,
    58  			"404": 1.4,
    59  		},
    60  		"grpc": {
    61  			"0": 14,
    62  			"7": 1.4,
    63  		},
    64  	}
    65  	assert.Equal(result, health.Requests.Inbound)
    66  	assert.Equal(emptyResult, health.Requests.Outbound)
    67  }
    68  
    69  func TestGetAppHealth(t *testing.T) {
    70  	assert := assert.New(t)
    71  	conf := config.NewConfig()
    72  	config.Set(conf)
    73  	objects := []runtime.Object{
    74  		&osproject_v1.Project{ObjectMeta: meta_v1.ObjectMeta{Name: "ns"}},
    75  		&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "ns"}},
    76  	}
    77  	for _, obj := range fakeDeploymentsHealthReview() {
    78  		o := obj
    79  		objects = append(objects, &o)
    80  	}
    81  	for _, obj := range fakePodsHealthReview() {
    82  		o := obj
    83  		objects = append(objects, &o)
    84  	}
    85  	k8s := kubetest.NewFakeK8sClient(objects...)
    86  	k8s.OpenShift = true
    87  	prom := new(prometheustest.PromClientMock)
    88  
    89  	clients := make(map[string]kubernetes.ClientInterface)
    90  	clients[conf.KubernetesConfig.ClusterName] = k8s
    91  
    92  	hs := HealthService{prom: prom, businessLayer: NewWithBackends(clients, clients, prom, nil), userClients: clients}
    93  
    94  	queryTime := time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC)
    95  	prom.MockAppRequestRates("ns", conf.KubernetesConfig.ClusterName, "reviews", otherRatesIn, otherRatesOut)
    96  
    97  	mockWkd := models.Workload{}
    98  	mockWkd.Name = "reviews-v1"
    99  	mockWkd.IstioSidecar = true
   100  
   101  	mockApp := appDetails{
   102  		Workloads: models.Workloads{&mockWkd},
   103  	}
   104  
   105  	health, _ := hs.GetAppHealth(context.TODO(), "ns", conf.KubernetesConfig.ClusterName, "reviews", "1m", queryTime, &mockApp)
   106  
   107  	prom.AssertNumberOfCalls(t, "GetAppRequestRates", 1)
   108  	result := map[string]map[string]float64{
   109  		"http": {
   110  			"500": 1.6,
   111  		},
   112  	}
   113  	assert.Equal(result, health.Requests.Inbound)
   114  	result = map[string]map[string]float64{
   115  		"http": {
   116  			"200": 5,
   117  			"400": 3.5,
   118  		},
   119  		"grpc": {
   120  			"0": 5,
   121  			"7": 3.5,
   122  		},
   123  	}
   124  	assert.Equal(result, health.Requests.Outbound)
   125  }
   126  
   127  func TestGetWorkloadHealth(t *testing.T) {
   128  	assert := assert.New(t)
   129  	conf := config.NewConfig()
   130  	config.Set(conf)
   131  	objects := []runtime.Object{
   132  		&osproject_v1.Project{ObjectMeta: meta_v1.ObjectMeta{Name: "ns"}},
   133  		&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "ns"}},
   134  		&fakeDeploymentsHealthReview()[0],
   135  	}
   136  	for _, obj := range fakePodsHealthReview() {
   137  		o := obj
   138  		objects = append(objects, &o)
   139  	}
   140  	k8s := kubetest.NewFakeK8sClient(objects...)
   141  	k8s.OpenShift = true
   142  	prom := new(prometheustest.PromClientMock)
   143  
   144  	queryTime := time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC)
   145  	prom.MockWorkloadRequestRates("ns", conf.KubernetesConfig.ClusterName, "reviews-v1", otherRatesIn, otherRatesOut)
   146  
   147  	clients := make(map[string]kubernetes.ClientInterface)
   148  	clients[conf.KubernetesConfig.ClusterName] = k8s
   149  	hs := HealthService{prom: prom, businessLayer: NewWithBackends(clients, clients, prom, nil), userClients: clients}
   150  
   151  	mockWorkload := models.Workload{}
   152  	mockWorkload.Name = "reviews-v1"
   153  	mockWorkload.IstioSidecar = true
   154  
   155  	health, _ := hs.GetWorkloadHealth(context.TODO(), "ns", conf.KubernetesConfig.ClusterName, "reviews-v1", "1m", queryTime, &mockWorkload)
   156  
   157  	prom.AssertNumberOfCalls(t, "GetWorkloadRequestRates", 1)
   158  	result := map[string]map[string]float64{
   159  		"http": {
   160  			"500": 1.6,
   161  		},
   162  	}
   163  	assert.Equal(result, health.Requests.Inbound)
   164  	result = map[string]map[string]float64{
   165  		"http": {
   166  			"200": 5,
   167  			"400": 3.5,
   168  		},
   169  		"grpc": {
   170  			"0": 5,
   171  			"7": 3.5,
   172  		},
   173  	}
   174  	assert.Equal(result, health.Requests.Outbound)
   175  }
   176  
   177  func TestGetAppHealthWithoutIstio(t *testing.T) {
   178  	assert := assert.New(t)
   179  	conf := config.NewConfig()
   180  
   181  	objects := []runtime.Object{
   182  		&osproject_v1.Project{ObjectMeta: meta_v1.ObjectMeta{Name: "ns"}},
   183  		&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "ns"}},
   184  	}
   185  	for _, obj := range fakeDeploymentsHealthReview() {
   186  		o := obj
   187  		objects = append(objects, &o)
   188  	}
   189  	for _, obj := range fakePodsHealthReviewWithoutIstio() {
   190  		o := obj
   191  		objects = append(objects, &o)
   192  	}
   193  	k8s := kubetest.NewFakeK8sClient(objects...)
   194  	prom := new(prometheustest.PromClientMock)
   195  
   196  	queryTime := time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC)
   197  	prom.MockAppRequestRates("ns", conf.KubernetesConfig.ClusterName, "reviews", otherRatesIn, otherRatesOut)
   198  
   199  	clients := make(map[string]kubernetes.ClientInterface)
   200  	clients[conf.KubernetesConfig.ClusterName] = k8s
   201  	hs := HealthService{prom: prom, businessLayer: NewWithBackends(clients, clients, prom, nil), userClients: clients}
   202  
   203  	mockApp := appDetails{}
   204  
   205  	health, _ := hs.GetAppHealth(context.TODO(), "ns", conf.KubernetesConfig.ClusterName, "reviews", "1m", queryTime, &mockApp)
   206  
   207  	prom.AssertNumberOfCalls(t, "GetAppRequestRates", 0)
   208  	assert.Equal(emptyResult, health.Requests.Inbound)
   209  	assert.Equal(emptyResult, health.Requests.Outbound)
   210  }
   211  
   212  func TestGetWorkloadHealthWithoutIstio(t *testing.T) {
   213  	assert := assert.New(t)
   214  	conf := config.NewConfig()
   215  	config.Set(conf)
   216  	objects := []runtime.Object{
   217  		&osproject_v1.Project{ObjectMeta: meta_v1.ObjectMeta{Name: "ns"}},
   218  		&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "ns"}},
   219  		&fakeDeploymentsHealthReview()[0],
   220  	}
   221  	for _, obj := range fakePodsHealthReviewWithoutIstio() {
   222  		o := obj
   223  		objects = append(objects, &o)
   224  	}
   225  	k8s := kubetest.NewFakeK8sClient(objects...)
   226  	k8s.OpenShift = true
   227  	prom := new(prometheustest.PromClientMock)
   228  
   229  	queryTime := time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC)
   230  	prom.MockWorkloadRequestRates("ns", conf.KubernetesConfig.ClusterName, "reviews-v1", otherRatesIn, otherRatesOut)
   231  
   232  	clients := make(map[string]kubernetes.ClientInterface)
   233  	clients[conf.KubernetesConfig.ClusterName] = k8s
   234  	hs := HealthService{prom: prom, businessLayer: NewWithBackends(clients, clients, prom, nil), userClients: clients}
   235  
   236  	mockWorkload := models.Workload{}
   237  	mockWorkload.Name = "reviews-v1"
   238  
   239  	health, _ := hs.GetWorkloadHealth(context.TODO(), "ns", conf.KubernetesConfig.ClusterName, "reviews-v1", "1m", queryTime, &mockWorkload)
   240  
   241  	prom.AssertNumberOfCalls(t, "GetWorkloadRequestRates", 0)
   242  	assert.Equal(emptyResult, health.Requests.Inbound)
   243  	assert.Equal(emptyResult, health.Requests.Outbound)
   244  }
   245  
   246  func TestGetNamespaceAppHealthWithoutIstio(t *testing.T) {
   247  	require := require.New(t)
   248  	conf := config.NewConfig()
   249  	config.Set(conf)
   250  
   251  	objects := []runtime.Object{
   252  		&osproject_v1.Project{ObjectMeta: meta_v1.ObjectMeta{Name: "ns"}},
   253  		&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "ns"}},
   254  	}
   255  	for _, obj := range fakeDeploymentsHealthReview() {
   256  		o := obj
   257  		objects = append(objects, &o)
   258  	}
   259  	for _, obj := range fakePodsHealthReviewWithoutIstio() {
   260  		o := obj
   261  		objects = append(objects, &o)
   262  	}
   263  	k8s := kubetest.NewFakeK8sClient(objects...)
   264  	k8s.OpenShift = true
   265  	prom := new(prometheustest.PromClientMock)
   266  	SetupBusinessLayer(t, k8s, *conf)
   267  
   268  	clients := make(map[string]kubernetes.ClientInterface)
   269  	clients[conf.KubernetesConfig.ClusterName] = k8s
   270  	hs := NewWithBackends(clients, clients, prom, nil).Health
   271  	criteria := NamespaceHealthCriteria{Cluster: conf.KubernetesConfig.ClusterName, Namespace: "ns", RateInterval: "1m", QueryTime: time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC), IncludeMetrics: true}
   272  
   273  	_, err := hs.GetNamespaceAppHealth(context.TODO(), criteria)
   274  	require.NoError(err)
   275  
   276  	// Make sure unnecessary call isn't performed
   277  	prom.AssertNumberOfCalls(t, "GetAllRequestRates", 0)
   278  }
   279  
   280  func TestGetNamespaceServiceHealthWithNA(t *testing.T) {
   281  	assert := assert.New(t)
   282  
   283  	conf := config.NewConfig()
   284  	config.Set(conf)
   285  	reviews := kubetest.FakeService("tutorial", "reviews")
   286  	httpbin := kubetest.FakeService("tutorial", "httpbin")
   287  	k8s := kubetest.NewFakeK8sClient(
   288  		&osproject_v1.Project{ObjectMeta: meta_v1.ObjectMeta{Name: "ns"}},
   289  		&osproject_v1.Project{ObjectMeta: meta_v1.ObjectMeta{Name: "tutorial"}},
   290  		&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "ns"}},
   291  		&reviews,
   292  		&httpbin,
   293  	)
   294  	k8s.OpenShift = true
   295  	prom := new(prometheustest.PromClientMock)
   296  	SetupBusinessLayer(t, k8s, *conf)
   297  
   298  	prom.On("GetNamespaceServicesRequestRates", "tutorial", conf.KubernetesConfig.ClusterName, mock.AnythingOfType("string"), mock.AnythingOfType("time.Time")).Return(serviceRates, nil)
   299  
   300  	clients := make(map[string]kubernetes.ClientInterface)
   301  	clients[conf.KubernetesConfig.ClusterName] = k8s
   302  	hs := HealthService{prom: prom, businessLayer: NewWithBackends(clients, clients, prom, nil), userClients: clients}
   303  
   304  	criteria := NamespaceHealthCriteria{Cluster: conf.KubernetesConfig.ClusterName, Namespace: "tutorial", RateInterval: "1m", QueryTime: time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC), IncludeMetrics: true}
   305  	health, err := hs.GetNamespaceServiceHealth(context.TODO(), criteria)
   306  
   307  	assert.Nil(err)
   308  	// Make sure we get services with N/A health
   309  	assert.Len(health, 2)
   310  	assert.Equal(emptyResult, health["reviews"].Requests.Inbound)
   311  	assert.Equal(emptyResult, health["reviews"].Requests.Outbound)
   312  	result := map[string]map[string]float64{
   313  		"http": {
   314  			"200": 14,
   315  			"404": 1.4,
   316  		},
   317  		"grpc": {
   318  			"0": 14,
   319  			"7": 1.4,
   320  		},
   321  	}
   322  	assert.Equal(result, health["httpbin"].Requests.Inbound)
   323  	assert.Equal(emptyResult, health["httpbin"].Requests.Outbound)
   324  }
   325  
   326  func TestGetNamespaceServicesHealthMultiCluster(t *testing.T) {
   327  	assert := assert.New(t)
   328  
   329  	conf := config.NewConfig()
   330  	conf.ExternalServices.Istio.IstioAPIEnabled = false
   331  	config.Set(conf)
   332  
   333  	clientFactory := kubetest.NewK8SClientFactoryMock(nil)
   334  	clients := map[string]kubernetes.ClientInterface{
   335  		conf.KubernetesConfig.ClusterName: kubetest.NewFakeK8sClient(
   336  			&core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: "tutorial"}},
   337  			&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "tutorial"}},
   338  		),
   339  		"west": kubetest.NewFakeK8sClient(
   340  			&core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: "tutorial"}},
   341  			&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "tutorial"}},
   342  		),
   343  	}
   344  	clientFactory.SetClients(clients)
   345  	cache := cache.NewTestingCacheWithFactory(t, clientFactory, *conf)
   346  	kialiCache = cache
   347  	prom := new(prometheustest.PromClientMock)
   348  	prom.On("GetNamespaceServicesRequestRates", "tutorial", conf.KubernetesConfig.ClusterName, mock.AnythingOfType("string"), mock.AnythingOfType("time.Time")).Return(serviceRates, nil)
   349  	prom.On("GetNamespaceServicesRequestRates", "tutorial", "west", mock.AnythingOfType("string"), mock.AnythingOfType("time.Time")).Return(serviceRates, nil)
   350  
   351  	layer := NewWithBackends(clients, clients, prom, nil)
   352  
   353  	hs := HealthService{prom: prom, businessLayer: layer, userClients: clients}
   354  
   355  	criteria := NamespaceHealthCriteria{Cluster: conf.KubernetesConfig.ClusterName, Namespace: "tutorial", RateInterval: "1m", QueryTime: time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC), IncludeMetrics: true}
   356  
   357  	servicesHealth, err := hs.GetNamespaceServiceHealth(context.TODO(), criteria)
   358  
   359  	assert.Nil(err)
   360  	assert.Len(servicesHealth, 1)
   361  }
   362  
   363  func TestGetNamespaceApplicationsHealthMultiCluster(t *testing.T) {
   364  	assert := assert.New(t)
   365  
   366  	conf := config.NewConfig()
   367  	conf.ExternalServices.Istio.IstioAPIEnabled = false
   368  	config.Set(conf)
   369  
   370  	clientFactory := kubetest.NewK8SClientFactoryMock(nil)
   371  	clients := map[string]kubernetes.ClientInterface{
   372  		conf.KubernetesConfig.ClusterName: kubetest.NewFakeK8sClient(
   373  			&core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: "tutorial"}},
   374  			&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "tutorial"}},
   375  			&core_v1.Pod{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "tutorial", Labels: map[string]string{"app": "httpbin", "version": "v1"}, Annotations: kubetest.FakeIstioAnnotations()}, Status: core_v1.PodStatus{Phase: core_v1.PodRunning}},
   376  		),
   377  		"west": kubetest.NewFakeK8sClient(
   378  			&core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: "tutorial"}},
   379  			&core_v1.Service{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "tutorial"}},
   380  			&core_v1.Pod{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "tutorial", Labels: map[string]string{"app": "httpbin", "version": "v1"}, Annotations: kubetest.FakeIstioAnnotations()}, Status: core_v1.PodStatus{Phase: core_v1.PodRunning}},
   381  		),
   382  	}
   383  	clientFactory.SetClients(clients)
   384  	cache := cache.NewTestingCacheWithFactory(t, clientFactory, *conf)
   385  	kialiCache = cache
   386  	prom := new(prometheustest.PromClientMock)
   387  	prom.On("GetAllRequestRates", "tutorial", conf.KubernetesConfig.ClusterName, "1m", mock.AnythingOfType("time.Time")).Return(serviceRates, nil)
   388  	prom.On("GetAllRequestRates", "tutorial", "west", "1m", mock.AnythingOfType("time.Time")).Return(serviceRates500, nil)
   389  
   390  	layer := NewWithBackends(clients, clients, prom, nil)
   391  
   392  	hs := HealthService{prom: prom, businessLayer: layer, userClients: clients}
   393  
   394  	criteria := NamespaceHealthCriteria{Namespace: "tutorial", Cluster: conf.KubernetesConfig.ClusterName, RateInterval: "1m", QueryTime: time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC), IncludeMetrics: true}
   395  
   396  	applicationsHealth, err := hs.GetNamespaceAppHealth(context.TODO(), criteria)
   397  
   398  	assert.Nil(err)
   399  	assert.Len(applicationsHealth, 1)
   400  	// Validate that west health is not included
   401  	assert.NotContains(applicationsHealth["httpbin"].Requests.Inbound["http"], "500")
   402  }
   403  
   404  func TestGetNamespaceWorkloadsHealthMultiCluster(t *testing.T) {
   405  	assert := assert.New(t)
   406  
   407  	conf := config.NewConfig()
   408  	conf.ExternalServices.Istio.IstioAPIEnabled = false
   409  	config.Set(conf)
   410  
   411  	clientFactory := kubetest.NewK8SClientFactoryMock(nil)
   412  	clients := map[string]kubernetes.ClientInterface{
   413  		conf.KubernetesConfig.ClusterName: kubetest.NewFakeK8sClient(
   414  			&core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: "tutorial"}},
   415  			&core_v1.Pod{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "tutorial", Labels: map[string]string{"app": "httpbin", "version": "v1"}, Annotations: kubetest.FakeIstioAnnotations()}, Status: core_v1.PodStatus{Phase: core_v1.PodRunning}},
   416  		),
   417  		"west": kubetest.NewFakeK8sClient(
   418  			&core_v1.Namespace{ObjectMeta: meta_v1.ObjectMeta{Name: "tutorial"}},
   419  			&core_v1.Pod{ObjectMeta: meta_v1.ObjectMeta{Name: "httpbin", Namespace: "tutorial", Labels: map[string]string{"app": "httpbin", "version": "v1"}, Annotations: kubetest.FakeIstioAnnotations()}, Status: core_v1.PodStatus{Phase: core_v1.PodRunning}},
   420  		),
   421  	}
   422  	clientFactory.SetClients(clients)
   423  	cache := cache.NewTestingCacheWithFactory(t, clientFactory, *conf)
   424  	kialiCache = cache
   425  	prom := new(prometheustest.PromClientMock)
   426  	prom.On("GetAllRequestRates", "tutorial", conf.KubernetesConfig.ClusterName, "1m", mock.AnythingOfType("time.Time")).Return(serviceRates, nil)
   427  	prom.On("GetAllRequestRates", "tutorial", "west", "1m", mock.AnythingOfType("time.Time")).Return(serviceRates500, nil)
   428  
   429  	layer := NewWithBackends(clients, clients, prom, nil)
   430  
   431  	hs := HealthService{prom: prom, businessLayer: layer, userClients: clients}
   432  
   433  	criteria := NamespaceHealthCriteria{Namespace: "tutorial", Cluster: conf.KubernetesConfig.ClusterName, RateInterval: "1m", QueryTime: time.Date(2017, 1, 15, 0, 0, 0, 0, time.UTC), IncludeMetrics: true}
   434  
   435  	workloadsHealth, err := hs.GetNamespaceAppHealth(context.TODO(), criteria)
   436  
   437  	assert.Nil(err)
   438  	assert.Len(workloadsHealth, 1)
   439  	assert.NotContains(workloadsHealth["httpbin"].Requests.Inbound["http"], "500")
   440  }
   441  
   442  var (
   443  	sampleReviewsToHttpbin200 = model.Sample{
   444  		Metric: model.Metric{
   445  			"destination_canonical_service": "httpbin",
   446  			"source_canonical_service":      "reviews",
   447  			"source_service":                "reviews.tutorial.svc.cluster.local",
   448  			"destination_service":           "httpbin.tutorial.svc.cluster.local",
   449  			"request_protocol":              "http",
   450  			"response_code":                 "200",
   451  			"reporter":                      "source",
   452  		},
   453  		Value:     model.SampleValue(5),
   454  		Timestamp: model.Now(),
   455  	}
   456  	sampleReviewsToHttpbin400 = model.Sample{
   457  		Metric: model.Metric{
   458  			"destination_canonical_service": "httpbin",
   459  			"source_canonical_service":      "reviews",
   460  			"source_service":                "reviews.tutorial.svc.cluster.local",
   461  			"destination_service":           "httpbin.tutorial.svc.cluster.local",
   462  			"request_protocol":              "http",
   463  			"response_code":                 "400",
   464  			"reporter":                      "source",
   465  		},
   466  		Value:     model.SampleValue(3.5),
   467  		Timestamp: model.Now(),
   468  	}
   469  	sampleReviewsToHttpbinGrpc0 = model.Sample{
   470  		Metric: model.Metric{
   471  			"destination_canonical_service": "httpbin",
   472  			"source_canonical_service":      "reviews",
   473  			"source_service":                "reviews.tutorial.svc.cluster.local",
   474  			"destination_service":           "httpbin.tutorial.svc.cluster.local",
   475  			"request_protocol":              "grpc",
   476  			"grpc_response_status":          "0",
   477  			"reporter":                      "source",
   478  		},
   479  		Value:     model.SampleValue(5),
   480  		Timestamp: model.Now(),
   481  	}
   482  	sampleReviewsToHttpbinGrpc7 = model.Sample{
   483  		Metric: model.Metric{
   484  			"destination_canonical_service": "httpbin",
   485  			"source_canonical_service":      "reviews",
   486  			"source_service":                "reviews.tutorial.svc.cluster.local",
   487  			"destination_service":           "httpbin.tutorial.svc.cluster.local",
   488  			"request_protocol":              "grpc",
   489  			"grpc_response_status":          "7",
   490  			"reporter":                      "source",
   491  		},
   492  		Value:     model.SampleValue(3.5),
   493  		Timestamp: model.Now(),
   494  	}
   495  	sampleUnknownToHttpbin200 = model.Sample{
   496  		Metric: model.Metric{
   497  			"destination_canonical_service": "httpbin",
   498  			"destination_service":           "httpbin.tutorial.svc.cluster.local",
   499  			"destination_service_name":      "httpbin",
   500  			"request_protocol":              "http",
   501  			"source_canonical_service":      "unknown",
   502  			"source_service":                "unknown",
   503  			"response_code":                 "200",
   504  		},
   505  		Value:     model.SampleValue(14),
   506  		Timestamp: model.Now(),
   507  	}
   508  	sampleUnknownToHttpbin404 = model.Sample{
   509  		Metric: model.Metric{
   510  			"destination_canonical_service": "httpbin",
   511  			"destination_service":           "httpbin.tutorial.svc.cluster.local",
   512  			"destination_service_name":      "httpbin",
   513  			"request_protocol":              "http",
   514  			"source_canonical_service":      "unknown",
   515  			"source_service":                "unknown",
   516  			"response_code":                 "404",
   517  		},
   518  		Value:     model.SampleValue(1.4),
   519  		Timestamp: model.Now(),
   520  	}
   521  	sampleUnknownToHttpbinGrpc0 = model.Sample{
   522  		Metric: model.Metric{
   523  			"destination_canonical_service": "httpbin",
   524  			"destination_service":           "httpbin.tutorial.svc.cluster.local",
   525  			"destination_service_name":      "httpbin",
   526  			"source_canonical_service":      "unknown",
   527  			"source_service":                "unknown",
   528  			"request_protocol":              "grpc",
   529  			"grpc_response_status":          "0",
   530  		},
   531  		Value:     model.SampleValue(14),
   532  		Timestamp: model.Now(),
   533  	}
   534  	sampleUnknownToHttpbinGrpc7 = model.Sample{
   535  		Metric: model.Metric{
   536  			"destination_canonical_service": "httpbin",
   537  			"destination_service":           "httpbin.tutorial.svc.cluster.local",
   538  			"destination_service_name":      "httpbin",
   539  			"source_canonical_service":      "unknown",
   540  			"source_service":                "unknown",
   541  			"request_protocol":              "grpc",
   542  			"grpc_response_status":          "7",
   543  		},
   544  		Value:     model.SampleValue(1.4),
   545  		Timestamp: model.Now(),
   546  	}
   547  	sampleUnknownToHttpbin500 = model.Sample{
   548  		Metric: model.Metric{
   549  			"destination_canonical_service": "httpbin",
   550  			"destination_service":           "httpbin.tutorial.svc.cluster.local",
   551  			"destination_service_name":      "httpbin",
   552  			"source_canonical_service":      "unknown",
   553  			"source_service":                "unknown",
   554  			"request_protocol":              "http",
   555  			"response_code":                 "500",
   556  		},
   557  		Value:     model.SampleValue(1.6),
   558  		Timestamp: model.Now(),
   559  	}
   560  	sampleUnknownToReviews500 = model.Sample{
   561  		Metric: model.Metric{
   562  			"destination_canonical_service": "reviews",
   563  			"destination_service":           "reviews.tutorial.svc.cluster.local",
   564  			"destination_service_name":      "reviews",
   565  			"request_protocol":              "http",
   566  			"source_canonical_service":      "unknown",
   567  			"source_service":                "unknown",
   568  			"response_code":                 "500",
   569  			"reporter":                      "source",
   570  		},
   571  		Value:     model.SampleValue(1.6),
   572  		Timestamp: model.Now(),
   573  	}
   574  	serviceRates = model.Vector{
   575  		&sampleUnknownToHttpbin200,
   576  		&sampleUnknownToHttpbin404,
   577  		&sampleUnknownToHttpbinGrpc0,
   578  		&sampleUnknownToHttpbinGrpc7,
   579  	}
   580  	serviceRates500 = model.Vector{
   581  		&sampleUnknownToHttpbin500,
   582  	}
   583  	otherRatesIn = model.Vector{
   584  		&sampleUnknownToReviews500,
   585  	}
   586  	otherRatesOut = model.Vector{
   587  		&sampleReviewsToHttpbin200,
   588  		&sampleReviewsToHttpbin400,
   589  		&sampleReviewsToHttpbinGrpc0,
   590  		&sampleReviewsToHttpbinGrpc7,
   591  	}
   592  )
   593  
   594  func fakePodsHealthReview() []core_v1.Pod {
   595  	return []core_v1.Pod{
   596  		{
   597  			ObjectMeta: meta_v1.ObjectMeta{
   598  				Name:        "reviews-v1",
   599  				Namespace:   "ns",
   600  				Labels:      map[string]string{"app": "reviews", "version": "v1"},
   601  				Annotations: kubetest.FakeIstioAnnotations(),
   602  			},
   603  		},
   604  		{
   605  			ObjectMeta: meta_v1.ObjectMeta{
   606  				Name:        "reviews-v2",
   607  				Namespace:   "ns",
   608  				Labels:      map[string]string{"app": "reviews", "version": "v2"},
   609  				Annotations: kubetest.FakeIstioAnnotations(),
   610  			},
   611  		},
   612  	}
   613  }
   614  
   615  func fakePodsHealthReviewWithoutIstio() []core_v1.Pod {
   616  	return []core_v1.Pod{
   617  		{
   618  			ObjectMeta: meta_v1.ObjectMeta{
   619  				Name:      "reviews-v1",
   620  				Namespace: "ns",
   621  				Labels:    map[string]string{"app": "reviews", "version": "v1"},
   622  			},
   623  		},
   624  		{
   625  			ObjectMeta: meta_v1.ObjectMeta{
   626  				Name:      "reviews-v2",
   627  				Namespace: "ns",
   628  				Labels:    map[string]string{"app": "reviews", "version": "v2"},
   629  			},
   630  		},
   631  	}
   632  }
   633  
   634  func fakeDeploymentsHealthReview() []apps_v1.Deployment {
   635  	return []apps_v1.Deployment{
   636  		{
   637  			ObjectMeta: meta_v1.ObjectMeta{
   638  				Name:      "reviews-v1",
   639  				Namespace: "ns",
   640  			},
   641  			Status: apps_v1.DeploymentStatus{
   642  				Replicas:            3,
   643  				AvailableReplicas:   2,
   644  				UnavailableReplicas: 1,
   645  			},
   646  			Spec: apps_v1.DeploymentSpec{
   647  				Selector: &meta_v1.LabelSelector{
   648  					MatchLabels: map[string]string{"app": "reviews", "version": "v1"},
   649  				},
   650  			},
   651  		},
   652  		{
   653  			ObjectMeta: meta_v1.ObjectMeta{
   654  				Name:      "reviews-v2",
   655  				Namespace: "ns",
   656  			},
   657  			Status: apps_v1.DeploymentStatus{
   658  				Replicas:            2,
   659  				AvailableReplicas:   1,
   660  				UnavailableReplicas: 1,
   661  			},
   662  			Spec: apps_v1.DeploymentSpec{
   663  				Selector: &meta_v1.LabelSelector{
   664  					MatchLabels: map[string]string{"app": "reviews", "version": "v2"},
   665  				},
   666  			},
   667  		},
   668  	}
   669  }