Adding unit test for CLI edges command (#2837)

Adds a unit test for the `linkerd edges` command.
This commit is contained in:
Carol A. Scott 2019-05-28 13:51:45 -07:00 committed by GitHub
parent b9cc66c6c8
commit 8c496e3d0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 212 additions and 7 deletions

View File

@ -112,14 +112,8 @@ func validateEdgesRequestInputs(targets []pb.Resource, options *edgesOptions) er
return fmt.Errorf("Edges cannot be returned for a specific resource name; remove %s from query", target.Name)
}
switch target.Type {
case "authority":
case "authority", "service", "all":
return fmt.Errorf("Resource type is not supported: %s", target.Type)
case "service":
return fmt.Errorf("Resource type is not supported: %s", target.Type)
case "all":
return fmt.Errorf("Resource type is not supported: %s", target.Type)
default:
return nil
}
}

153
cli/cmd/edges_test.go Normal file
View File

@ -0,0 +1,153 @@
package cmd
import (
"testing"
"github.com/linkerd/linkerd2/controller/api/public"
)
type edgesParamsExp struct {
options *edgesOptions
resSrc []string
resDst []string
resClient []string
resServer []string
resMsg []string
resourceType string
file string
}
func TestEdges(t *testing.T) {
// response content for SRC, DST, CLIENT, SERVER and MSG
var (
resSrc = []string{
"web-57b7f9db85-297dw",
"web-57b7f9db85-297dw",
"vote-bot-7466ffc7f7-5rc4l",
}
resDst = []string{
"emoji-646ddcc5f9-zjgs9",
"voting-689f845d98-rj6nz",
"web-57b7f9db85-297dw",
}
resClient = []string{
"web.emojivoto.serviceaccount.identity.linkerd.cluster.local",
"web.emojivoto.serviceaccount.identity.linkerd.cluster.local",
"default.emojivoto.serviceaccount.identity.linkerd.cluster.local",
}
resServer = []string{
"emoji.emojivoto.serviceaccount.identity.linkerd.cluster.local",
"voting.emojivoto.serviceaccount.identity.linkerd.cluster.local",
"web.emojivoto.serviceaccount.identity.linkerd.cluster.local",
}
resMsg = []string{"", "", ""}
)
options := newEdgesOptions()
options.namespace = "emojivoto"
options.outputFormat = tableOutput
t.Run("Returns edges", func(t *testing.T) {
testEdgesCall(edgesParamsExp{
options: options,
resourceType: "pod",
resSrc: resSrc,
resDst: resDst,
resClient: resClient,
resServer: resServer,
resMsg: resMsg,
file: "edges_one_output.golden",
}, t)
})
options.outputFormat = jsonOutput
t.Run("Returns edges (json)", func(t *testing.T) {
testEdgesCall(edgesParamsExp{
options: options,
resourceType: "pod",
resSrc: resSrc,
resDst: resDst,
resClient: resClient,
resServer: resServer,
resMsg: resMsg,
file: "edges_one_output_json.golden",
}, t)
})
t.Run("Returns an error if outputFormat specified is not table or json", func(t *testing.T) {
options.outputFormat = wideOutput
args := []string{"pod"}
expectedError := "--output currently only supports table and json"
_, err := buildEdgesRequests(args, options)
if err == nil || err.Error() != expectedError {
t.Fatalf("Expected error [%s] instead got [%s]", expectedError, err)
}
})
t.Run("Returns an error if request includes the resource name", func(t *testing.T) {
options.outputFormat = tableOutput
args := []string{"pod/pod-name"}
expectedError := "Edges cannot be returned for a specific resource name; remove pod-name from query"
_, err := buildEdgesRequests(args, options)
if err == nil || err.Error() != expectedError {
t.Fatalf("Expected error [%s] instead got [%s]", expectedError, err)
}
})
t.Run("Returns an error if request is for authority", func(t *testing.T) {
options.outputFormat = tableOutput
args := []string{"authority"}
expectedError := "Resource type is not supported: authority"
_, err := buildEdgesRequests(args, options)
if err == nil || err.Error() != expectedError {
t.Fatalf("Expected error [%s] instead got [%s]", expectedError, err)
}
})
t.Run("Returns an error if request is for service", func(t *testing.T) {
options.outputFormat = tableOutput
args := []string{"service"}
expectedError := "Resource type is not supported: service"
_, err := buildEdgesRequests(args, options)
if err == nil || err.Error() != expectedError {
t.Fatalf("Expected error [%s] instead got [%s]", expectedError, err)
}
})
t.Run("Returns an error if request is for all resource types", func(t *testing.T) {
options.outputFormat = tableOutput
args := []string{"all"}
expectedError := "Resource type is not supported: all"
_, err := buildEdgesRequests(args, options)
if err == nil || err.Error() != expectedError {
t.Fatalf("Expected error [%s] instead got [%s]", expectedError, err)
}
})
}
func testEdgesCall(exp edgesParamsExp, t *testing.T) {
mockClient := &public.MockAPIClient{}
response := public.GenEdgesResponse(exp.resourceType, exp.resSrc, exp.resDst, exp.resClient, exp.resServer, exp.resMsg)
mockClient.EdgesResponseToReturn = &response
args := []string{"pod"}
reqs, err := buildEdgesRequests(args, exp.options)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
resp, err := requestEdgesFromAPI(mockClient, reqs[0])
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
rows := edgesRespToRows(resp)
output := renderEdgeStats(rows, exp.options)
diffTestdata(t, exp.file, output)
}

View File

@ -0,0 +1,4 @@
SRC DST CLIENT SERVER MSG
web-57b7f9db85-297dw emoji-646ddcc5f9-zjgs9 web.emojivoto emoji.emojivoto -
web-57b7f9db85-297dw voting-689f845d98-rj6nz web.emojivoto voting.emojivoto -
vote-bot-7466ffc7f7-5rc4l web-57b7f9db85-297dw default.emojivoto web.emojivoto -

View File

@ -0,0 +1,23 @@
[
{
"src": "web-57b7f9db85-297dw",
"dst": "emoji-646ddcc5f9-zjgs9",
"client_id": "web.emojivoto",
"server_id": "emoji.emojivoto",
"no_tls_reason": "-"
},
{
"src": "web-57b7f9db85-297dw",
"dst": "voting-689f845d98-rj6nz",
"client_id": "web.emojivoto",
"server_id": "voting.emojivoto",
"no_tls_reason": "-"
},
{
"src": "vote-bot-7466ffc7f7-5rc4l",
"dst": "web-57b7f9db85-297dw",
"client_id": "default.emojivoto",
"server_id": "web.emojivoto",
"no_tls_reason": "-"
}
]

View File

@ -228,6 +228,37 @@ func GenStatSummaryResponse(resName, resType string, resNs []string, counts *Pod
return resp
}
// GenEdgesResponse generates a mock Public API StatSummaryResponse
// object.
func GenEdgesResponse(resourceType string, resSrc, resDst, resClient, resServer, msg []string) pb.EdgesResponse {
edges := []*pb.Edge{}
for i := range resSrc {
edge := &pb.Edge{
Src: &pb.Resource{
Name: resSrc[i],
Type: resourceType,
},
Dst: &pb.Resource{
Name: resDst[i],
Type: resourceType,
},
ClientId: resClient[i],
ServerId: resServer[i],
NoIdentityMsg: msg[i],
}
edges = append(edges, edge)
}
resp := pb.EdgesResponse{
Response: &pb.EdgesResponse_Ok_{
Ok: &pb.EdgesResponse_Ok{
Edges: edges,
},
},
}
return resp
}
// GenTopRoutesResponse generates a mock Public API TopRoutesResponse object.
func GenTopRoutesResponse(routes []string, counts []uint64, outbound bool, authority string) pb.TopRoutesResponse {
rows := []*pb.RouteTable_Row{}