mirror of https://github.com/linkerd/linkerd2.git
Fix success rate calculation in public api (#723)
The success rate calculation relies on the `classification` label, but was incorrectly specifying `fail` rather than `failure`. Fix public api to specify `failure`. Also re-org public api tests for easier Kubernetes and Prometheus mocking. Signed-off-by: Andrew Seigner <siggy@buoyant.io>
This commit is contained in:
parent
bc16034fd6
commit
3a341abe9a
|
@ -198,7 +198,7 @@ func TestStat(t *testing.T) {
|
|||
&mockTelemetry{test: t, tRes: tr.tRes, mReq: tr.mReq},
|
||||
tap.NewTapClient(nil),
|
||||
fake.NewSimpleClientset(),
|
||||
&fakeProm{},
|
||||
&MockProm{},
|
||||
"conduit",
|
||||
)
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ func processRequests(vec model.Vector, labelSelector string) map[string]*pb.Basi
|
|||
switch string(sample.Metric[model.LabelName("classification")]) {
|
||||
case "success":
|
||||
result[label].SuccessCount = uint64(sample.Value)
|
||||
case "fail":
|
||||
case "failure":
|
||||
result[label].FailureCount = uint64(sample.Value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,10 @@ package public
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
promv1 "github.com/prometheus/client_golang/api/prometheus/v1"
|
||||
"github.com/prometheus/common/model"
|
||||
tap "github.com/runconduit/conduit/controller/gen/controller/tap"
|
||||
pb "github.com/runconduit/conduit/controller/gen/public"
|
||||
|
@ -14,48 +13,35 @@ import (
|
|||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
type fakeProm struct{}
|
||||
|
||||
func (f *fakeProm) Query(ctx context.Context, query string, ts time.Time) (model.Value, error) {
|
||||
return model.Value(model.Vector{}), nil
|
||||
type statSumExpected struct {
|
||||
err error
|
||||
promRes model.Value
|
||||
req pb.StatSummaryRequest
|
||||
res pb.StatSummaryResponse
|
||||
}
|
||||
func (f *fakeProm) QueryRange(ctx context.Context, query string, r promv1.Range) (model.Value, error) {
|
||||
return model.Value(model.Vector{}), nil
|
||||
}
|
||||
func (f *fakeProm) LabelValues(ctx context.Context, label string) (model.LabelValues, error) {
|
||||
return model.LabelValues{}, nil
|
||||
}
|
||||
func (f *fakeProm) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, error) {
|
||||
return []model.LabelSet{}, nil
|
||||
}
|
||||
|
||||
var (
|
||||
fakeGrpcServer = newGrpcServer(
|
||||
&mockTelemetry{},
|
||||
tap.NewTapClient(nil),
|
||||
fake.NewSimpleClientset(),
|
||||
&fakeProm{},
|
||||
"conduit",
|
||||
)
|
||||
)
|
||||
|
||||
func TestStatSummary(t *testing.T) {
|
||||
t.Run("Successfully performs a query based on resource type", func(t *testing.T) {
|
||||
expectations := map[pb.StatSummaryRequest]pb.StatSummaryResponse{
|
||||
pb.StatSummaryRequest{
|
||||
Selector: &pb.ResourceSelection{
|
||||
Resource: &pb.Resource{
|
||||
Type: k8s.KubernetesDeployments,
|
||||
expectations := []statSumExpected{
|
||||
statSumExpected{
|
||||
err: nil,
|
||||
promRes: model.Value(model.Vector{}),
|
||||
req: pb.StatSummaryRequest{
|
||||
Selector: &pb.ResourceSelection{
|
||||
Resource: &pb.Resource{
|
||||
Type: k8s.KubernetesDeployments,
|
||||
},
|
||||
},
|
||||
},
|
||||
}: pb.StatSummaryResponse{
|
||||
Response: &pb.StatSummaryResponse_Ok_{ // https://github.com/golang/protobuf/issues/205
|
||||
Ok: &pb.StatSummaryResponse_Ok{
|
||||
StatTables: []*pb.StatTable{
|
||||
&pb.StatTable{
|
||||
Table: &pb.StatTable_PodGroup_{
|
||||
PodGroup: &pb.StatTable_PodGroup{
|
||||
Rows: []*pb.StatTable_PodGroup_Row{},
|
||||
res: pb.StatSummaryResponse{
|
||||
Response: &pb.StatSummaryResponse_Ok_{ // https://github.com/golang/protobuf/issues/205
|
||||
Ok: &pb.StatSummaryResponse_Ok{
|
||||
StatTables: []*pb.StatTable{
|
||||
&pb.StatTable{
|
||||
Table: &pb.StatTable_PodGroup_{
|
||||
PodGroup: &pb.StatTable_PodGroup{
|
||||
Rows: []*pb.StatTable_PodGroup_Row{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -65,51 +51,76 @@ func TestStatSummary(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
for req, expectedRsp := range expectations {
|
||||
rsp, err := fakeGrpcServer.StatSummary(context.TODO(), &req)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err)
|
||||
for _, exp := range expectations {
|
||||
fakeGrpcServer := newGrpcServer(
|
||||
&mockTelemetry{},
|
||||
tap.NewTapClient(nil),
|
||||
fake.NewSimpleClientset(),
|
||||
&MockProm{Res: exp.promRes},
|
||||
"conduit",
|
||||
)
|
||||
|
||||
rsp, err := fakeGrpcServer.StatSummary(context.TODO(), &exp.req)
|
||||
if err != exp.err {
|
||||
t.Fatalf("Expected error: %s, Got: %s", exp.err, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(expectedRsp, *rsp) {
|
||||
t.Fatalf("Expected: %+v, Got: %+v", &expectedRsp, rsp)
|
||||
if !reflect.DeepEqual(exp.res, *rsp) {
|
||||
t.Fatalf("Expected: %+v, Got: %+v", &exp.res, rsp)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Given an invalid resource type, returns error", func(t *testing.T) {
|
||||
expectations := map[pb.StatSummaryRequest]string{
|
||||
pb.StatSummaryRequest{
|
||||
Selector: &pb.ResourceSelection{
|
||||
Resource: &pb.Resource{
|
||||
Type: "badtype",
|
||||
expectations := []statSumExpected{
|
||||
statSumExpected{
|
||||
err: errors.New("Unimplemented resource type: badtype"),
|
||||
req: pb.StatSummaryRequest{
|
||||
Selector: &pb.ResourceSelection{
|
||||
Resource: &pb.Resource{
|
||||
Type: "badtype",
|
||||
},
|
||||
},
|
||||
},
|
||||
}: "Unimplemented resource type: badtype",
|
||||
pb.StatSummaryRequest{
|
||||
Selector: &pb.ResourceSelection{
|
||||
Resource: &pb.Resource{
|
||||
Type: "deployment",
|
||||
},
|
||||
statSumExpected{
|
||||
err: errors.New("Unimplemented resource type: deployment"),
|
||||
req: pb.StatSummaryRequest{
|
||||
Selector: &pb.ResourceSelection{
|
||||
Resource: &pb.Resource{
|
||||
Type: "deployment",
|
||||
},
|
||||
},
|
||||
},
|
||||
}: "Unimplemented resource type: deployment",
|
||||
pb.StatSummaryRequest{
|
||||
Selector: &pb.ResourceSelection{
|
||||
Resource: &pb.Resource{
|
||||
Type: "pod",
|
||||
},
|
||||
statSumExpected{
|
||||
err: errors.New("Unimplemented resource type: pod"),
|
||||
req: pb.StatSummaryRequest{
|
||||
Selector: &pb.ResourceSelection{
|
||||
Resource: &pb.Resource{
|
||||
Type: "pod",
|
||||
},
|
||||
},
|
||||
},
|
||||
}: "Unimplemented resource type: pod",
|
||||
},
|
||||
}
|
||||
|
||||
for req, msg := range expectations {
|
||||
_, err := fakeGrpcServer.StatSummary(context.TODO(), &req)
|
||||
if err == nil {
|
||||
t.Fatalf("StatSummary(%+v) unexpectedly succeeded, should have returned %s", req, msg)
|
||||
}
|
||||
for _, exp := range expectations {
|
||||
fakeGrpcServer := newGrpcServer(
|
||||
&mockTelemetry{},
|
||||
tap.NewTapClient(nil),
|
||||
fake.NewSimpleClientset(),
|
||||
&MockProm{Res: exp.promRes},
|
||||
"conduit",
|
||||
)
|
||||
|
||||
if err.Error() != msg {
|
||||
t.Fatalf("StatSummary(%+v) should have returned: %s but got unexpected message: %s", req, msg, err)
|
||||
_, err := fakeGrpcServer.StatSummary(context.TODO(), &exp.req)
|
||||
if err != nil || exp.err != nil {
|
||||
if (err == nil && exp.err != nil) ||
|
||||
(err != nil && exp.err == nil) ||
|
||||
(err.Error() != exp.err.Error()) {
|
||||
t.Fatalf("Unexpected error (Expected: %s, Got: %s)", exp.err, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -3,7 +3,10 @@ package public
|
|||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/api/prometheus/v1"
|
||||
"github.com/prometheus/common/model"
|
||||
common "github.com/runconduit/conduit/controller/gen/common"
|
||||
healthcheckPb "github.com/runconduit/conduit/controller/gen/common/healthcheck"
|
||||
pb "github.com/runconduit/conduit/controller/gen/public"
|
||||
|
@ -65,3 +68,22 @@ func (a *MockApi_TapClient) Recv() (*common.TapEvent, error) {
|
|||
|
||||
return &eventPopped, errorPopped
|
||||
}
|
||||
|
||||
type MockProm struct {
|
||||
api v1.API
|
||||
Res model.Value
|
||||
}
|
||||
|
||||
// satisfies v1.API
|
||||
func (m *MockProm) Query(ctx context.Context, query string, ts time.Time) (model.Value, error) {
|
||||
return m.Res, nil
|
||||
}
|
||||
func (m *MockProm) QueryRange(ctx context.Context, query string, r v1.Range) (model.Value, error) {
|
||||
return m.Res, nil
|
||||
}
|
||||
func (m *MockProm) LabelValues(ctx context.Context, label string) (model.LabelValues, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *MockProm) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -5,32 +5,12 @@ import (
|
|||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/api/prometheus/v1"
|
||||
"github.com/prometheus/common/model"
|
||||
"github.com/runconduit/conduit/controller/api/public"
|
||||
read "github.com/runconduit/conduit/controller/gen/controller/telemetry"
|
||||
)
|
||||
|
||||
type mockProm struct {
|
||||
api v1.API
|
||||
res model.Value
|
||||
}
|
||||
|
||||
// satisfies v1.API
|
||||
func (m *mockProm) Query(ctx context.Context, query string, ts time.Time) (model.Value, error) {
|
||||
return m.res, nil
|
||||
}
|
||||
func (m *mockProm) QueryRange(ctx context.Context, query string, r v1.Range) (model.Value, error) {
|
||||
return m.res, nil
|
||||
}
|
||||
func (m *mockProm) LabelValues(ctx context.Context, label string) (model.LabelValues, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (m *mockProm) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type testResponse struct {
|
||||
err error
|
||||
promRes model.Value
|
||||
|
@ -157,7 +137,7 @@ func TestServerResponses(t *testing.T) {
|
|||
t.Run("Queries return the expected responses", func(t *testing.T) {
|
||||
for _, tr := range responses {
|
||||
s := server{
|
||||
prometheusAPI: &mockProm{res: tr.promRes},
|
||||
prometheusAPI: &public.MockProm{Res: tr.promRes},
|
||||
}
|
||||
res, err := s.Query(context.Background(), tr.queryReq)
|
||||
if err != nil || tr.err != nil {
|
||||
|
|
Loading…
Reference in New Issue