...

Source file src/github.com/linkerd/linkerd2/viz/metrics-api/edges_test.go

Documentation: github.com/linkerd/linkerd2/viz/metrics-api

     1  package api
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"testing"
     8  
     9  	pkgK8s "github.com/linkerd/linkerd2/pkg/k8s"
    10  	pb "github.com/linkerd/linkerd2/viz/metrics-api/gen/viz"
    11  	"github.com/prometheus/common/model"
    12  	"google.golang.org/protobuf/proto"
    13  )
    14  
    15  const (
    16  	serverIDLabel = model.LabelName("server_id")
    17  	resourceLabel = model.LabelName("deployment")
    18  	podLabel      = model.LabelName("pod")
    19  )
    20  
    21  type edgesExpected struct {
    22  	expectedStatRPC
    23  	req              *pb.EdgesRequest  // the request we would like to test
    24  	expectedResponse *pb.EdgesResponse // the edges response we expect
    25  }
    26  
    27  func genOutboundPromSample(resourceNamespace, resourceName, resourceNameDst, resourceNamespaceDst, serverID string) *model.Sample {
    28  	dstResourceLabel := "dst_" + resourceLabel
    29  
    30  	return &model.Sample{
    31  		Metric: model.Metric{
    32  			resourceLabel:     model.LabelValue(resourceName),
    33  			namespaceLabel:    model.LabelValue(resourceNamespace),
    34  			dstNamespaceLabel: model.LabelValue(resourceNamespaceDst),
    35  			dstResourceLabel:  model.LabelValue(resourceNameDst),
    36  			serverIDLabel:     model.LabelValue(serverID),
    37  			podLabel:          model.LabelValue(resourceName + "-0"),
    38  		},
    39  		Value:     123,
    40  		Timestamp: 456,
    41  	}
    42  }
    43  
    44  func genPod(name, namespace, sa string) string {
    45  	return fmt.Sprintf(`apiVersion: v1
    46  kind: Pod
    47  metadata:
    48    name: %s
    49    namespace: %s
    50  spec:
    51    containers:
    52    - name: linkerd-proxy
    53      env:
    54      - name: LINKERD2_PROXY_IDENTITY_LOCAL_NAME
    55        value: $(_pod_sa).$(_pod_ns).serviceaccount.identity.linkerd.cluster.local
    56    serviceAccountName: %s
    57  status:
    58    phase: Running
    59  `, name, namespace, sa)
    60  }
    61  
    62  func testEdges(t *testing.T, expectations []edgesExpected) {
    63  	for _, exp := range expectations {
    64  		mockProm, fakeGrpcServer, err := newMockGrpcServer(exp.expectedStatRPC)
    65  		if err != nil {
    66  			t.Fatalf("Error creating mock grpc server: %s", err)
    67  		}
    68  
    69  		rsp, err := fakeGrpcServer.Edges(context.TODO(), exp.req)
    70  		if !errors.Is(err, exp.err) {
    71  			t.Fatalf("Expected error: %s, Got: %s", exp.err, err)
    72  		}
    73  
    74  		err = exp.verifyPromQueries(mockProm)
    75  		if err != nil {
    76  			t.Fatal(err)
    77  		}
    78  
    79  		rspEdgeRows := rsp.GetOk().Edges
    80  
    81  		if len(rspEdgeRows) != len(exp.expectedResponse.GetOk().Edges) {
    82  			t.Fatalf(
    83  				"Expected [%d] edge rows, got [%d].\nExpected:\n%s\nGot:\n%s",
    84  				len(exp.expectedResponse.GetOk().Edges),
    85  				len(rspEdgeRows),
    86  				exp.expectedResponse.GetOk().Edges,
    87  				rspEdgeRows,
    88  			)
    89  		}
    90  
    91  		for i, st := range rspEdgeRows {
    92  			expected := exp.expectedResponse.GetOk().Edges[i]
    93  			if !proto.Equal(st, expected) {
    94  				t.Fatalf("Expected: %+v\n Got: %+v\n", expected, st)
    95  			}
    96  		}
    97  
    98  		if !proto.Equal(exp.expectedResponse.GetOk(), rsp.GetOk()) {
    99  			t.Fatalf("Expected edgesOkResp: %+v\n Got: %+v", &exp.expectedResponse, rsp)
   100  		}
   101  	}
   102  }
   103  
   104  func TestEdges(t *testing.T) {
   105  	mockPromResponse := model.Vector{
   106  		genOutboundPromSample("emojivoto", "web", "emoji", "emojivoto", "emoji.emojivoto.serviceaccount.identity.linkerd.cluster.local"),
   107  		genOutboundPromSample("emojivoto", "web", "voting", "emojivoto", "voting.emojivoto.serviceaccount.identity.linkerd.cluster.local"),
   108  		genOutboundPromSample("emojivoto", "vote-bot", "web", "emojivoto", "web.emojivoto.serviceaccount.identity.linkerd.cluster.local"),
   109  		genOutboundPromSample("linkerd", "linkerd-identity", "linkerd-prometheus", "linkerd", "linkerd-prometheus.linkerd.serviceaccount.identity.linkerd.cluster.local"),
   110  	}
   111  	pods := []string{
   112  		genPod("web-0", "emojivoto", "web"),
   113  		genPod("vote-bot-0", "emojivoto", "default"),
   114  		genPod("linkerd-identity-0", "linkerd", "linkerd-identity"),
   115  	}
   116  
   117  	t.Run("Successfully returns edges for resource type Deployment and namespace emojivoto", func(t *testing.T) {
   118  		expectations := []edgesExpected{
   119  			{
   120  				expectedStatRPC: expectedStatRPC{
   121  					err:              nil,
   122  					mockPromResponse: mockPromResponse,
   123  					k8sConfigs:       pods,
   124  				},
   125  				req: &pb.EdgesRequest{
   126  					Selector: &pb.ResourceSelection{
   127  						Resource: &pb.Resource{
   128  							Namespace: "emojivoto",
   129  							Type:      pkgK8s.Deployment,
   130  						},
   131  					},
   132  				},
   133  				expectedResponse: GenEdgesResponse("deployment", "emojivoto"),
   134  			}}
   135  
   136  		testEdges(t, expectations)
   137  	})
   138  
   139  	t.Run("Successfully returns edges for resource type Deployment and namespace linkerd", func(t *testing.T) {
   140  		expectations := []edgesExpected{
   141  			{
   142  				expectedStatRPC: expectedStatRPC{
   143  					err:              nil,
   144  					mockPromResponse: mockPromResponse,
   145  					k8sConfigs:       pods,
   146  				},
   147  				req: &pb.EdgesRequest{
   148  					Selector: &pb.ResourceSelection{
   149  						Resource: &pb.Resource{
   150  							Namespace: "linkerd",
   151  							Type:      pkgK8s.Deployment,
   152  						},
   153  					},
   154  				},
   155  				expectedResponse: GenEdgesResponse("deployment", "linkerd"),
   156  			}}
   157  
   158  		testEdges(t, expectations)
   159  	})
   160  
   161  	t.Run("Successfully returns edges for resource type Deployment and all namespaces", func(t *testing.T) {
   162  		expectations := []edgesExpected{
   163  			{
   164  				expectedStatRPC: expectedStatRPC{
   165  					err:              nil,
   166  					mockPromResponse: mockPromResponse,
   167  					k8sConfigs:       pods,
   168  				},
   169  				req: &pb.EdgesRequest{
   170  					Selector: &pb.ResourceSelection{
   171  						Resource: &pb.Resource{
   172  							Type: pkgK8s.Deployment,
   173  						},
   174  					},
   175  				},
   176  				expectedResponse: GenEdgesResponse("deployment", "all"),
   177  			}}
   178  
   179  		testEdges(t, expectations)
   180  	})
   181  }
   182  

View as plain text