Skip to content

Commit

Permalink
Make tap command testablë
Browse files Browse the repository at this point in the history
  • Loading branch information
Phil Calcado committed Dec 22, 2017
1 parent 965d813 commit c49c7e7
Show file tree
Hide file tree
Showing 6 changed files with 306 additions and 64 deletions.
12 changes: 6 additions & 6 deletions cli/cmd/stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,25 @@ Valid resource types include:
The optional [TARGET] option can be either a name for a deployment or pod resource`,
RunE: func(cmd *cobra.Command, args []string) error {
var friendlyName string
var friendlyNameForResourceType string

switch len(args) {
case 1:
friendlyName = args[0]
friendlyNameForResourceType = args[0]
case 2:
friendlyName = args[0]
friendlyNameForResourceType = args[0]
target = args[1]
default:
return errors.New("please specify a resource type: pods, deployments or paths")
}

validatedResourceType, err := k8s.CanonicalKubernetesNameFromFriendlyName(friendlyName)
validatedResourceType, err := k8s.CanonicalKubernetesNameFromFriendlyName(friendlyNameForResourceType)
if err != nil {
switch friendlyName {
switch friendlyNameForResourceType {
case "paths", "path", "pa":
validatedResourceType = ConduitPaths
default:
return fmt.Errorf("invalid resource type %s, only %v are allowed as resource types", friendlyName, []string{k8s.KubernetesPods, k8s.KubernetesDeployments, ConduitPaths})
return fmt.Errorf("invalid resource type %s, only %v are allowed as resource types", friendlyNameForResourceType, []string{k8s.KubernetesPods, k8s.KubernetesDeployments, ConduitPaths})
}
}
kubeApi, err := k8s.MakeK8sAPi(shell.MakeUnixShell(), kubeconfigPath, apiAddr)
Expand Down
143 changes: 90 additions & 53 deletions cli/cmd/tap.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package cmd

import (
"bytes"
"context"
"errors"
"fmt"
"io"
"os"
"strings"
"text/tabwriter"

"github.com/runconduit/conduit/cli/k8s"
"github.com/runconduit/conduit/cli/shell"
Expand Down Expand Up @@ -39,57 +41,46 @@ Valid targets include:
* Pods (default/hello-world-h4fb2)
* Deployments (default/hello-world)`,
RunE: func(cmd *cobra.Command, args []string) error {
switch len(args) {
case 2:
resourceType := strings.ToLower(args[0])

// We don't validate inputs because they are validated on the server.
req := &pb.TapRequest{
MaxRps: maxRps,
ToPort: toPort,
ToIP: toIP,
FromPort: fromPort,
FromIP: fromIP,
Scheme: scheme,
Method: method,
Authority: authority,
Path: path,
}

switch resourceType {
case "deploy", "deployment", "deployments":
req.Target = &pb.TapRequest_Deployment{
Deployment: args[1],
}

case "po", "pod", "pods":
req.Target = &pb.TapRequest_Pod{
Pod: args[1],
}

default:
return errors.New("invalid target type")
}

kubeApi, err := k8s.MakeK8sAPi(shell.MakeUnixShell(), kubeconfigPath, apiAddr)
if err != nil {
return err
}

client, err := newApiClient(kubeApi)
if err != nil {
return err
}
rsp, err := client.Tap(context.Background(), req)
if err != nil {
return err
}
print(rsp)

return nil
default:
if len(args) != 2 {
return errors.New("please specify a target")
}

// We don't validate inputs because they are validated on the server.
partialReq := &pb.TapRequest{
MaxRps: maxRps,
ToPort: toPort,
ToIP: toIP,
FromPort: fromPort,
FromIP: fromIP,
Scheme: scheme,
Method: method,
Authority: authority,
Path: path,
}

friendlyNameForResourceType := strings.ToLower(args[0])
validatedResourceType, err := k8s.CanonicalKubernetesNameFromFriendlyName(friendlyNameForResourceType)
if err != nil {
return fmt.Errorf("unsupported resourceType [%s]", friendlyNameForResourceType)
}

kubeApi, err := k8s.MakeK8sAPi(shell.MakeUnixShell(), kubeconfigPath, apiAddr)
if err != nil {
return err
}

client, err := newApiClient(kubeApi)
if err != nil {
return err
}

output, err := requestTapFromApi(client, args[1], validatedResourceType, partialReq)
if err != nil {
return err
}
_, err = fmt.Print(output)

return err
},
}

Expand All @@ -107,7 +98,46 @@ func init() {
tapCmd.PersistentFlags().StringVar(&path, "path", "", "Display requests with paths that start with this prefix")
}

func print(rsp pb.Api_TapClient) {
func requestTapFromApi(client pb.ApiClient, targetName string, resourceType string, req *pb.TapRequest) (string, error) {
switch resourceType {
case k8s.KubernetesDeployments:
req.Target = &pb.TapRequest_Deployment{
Deployment: targetName,
}

case k8s.KubernetesPods:
req.Target = &pb.TapRequest_Pod{
Pod: targetName,
}
default:
return "", fmt.Errorf("unsupported resourceType [%s]", resourceType)
}

rsp, err := client.Tap(context.Background(), req)
if err != nil {
return "", err
}

return renderTap(rsp)
}

func renderTap(rsp pb.Api_TapClient) (string, error) {
var buffer bytes.Buffer
w := tabwriter.NewWriter(&buffer, 0, 0, 0, ' ', tabwriter.AlignRight)
err := writeTapEvenToBuffer(rsp, w)
if err != nil {
return "", err
}
w.Flush()

// strip left padding on the first column
out := string(buffer.Bytes())

return out, nil

}

func writeTapEvenToBuffer(rsp pb.Api_TapClient, w *tabwriter.Writer) error {
for {
event, err := rsp.Recv()
if err == io.EOF {
Expand All @@ -117,17 +147,24 @@ func print(rsp pb.Api_TapClient) {
fmt.Fprintln(os.Stderr, err)
break
}
fmt.Println(eventToString(event))
_, err = fmt.Fprintln(w, renderTapEvent(event))
if err != nil {
return err
}
}

return nil
}

func eventToString(event *common.TapEvent) string {
func renderTapEvent(event *common.TapEvent) string {
flow := fmt.Sprintf("src=%s dst=%s",
util.AddressToString(event.GetSource()),
util.AddressToString(event.GetTarget()),
)

switch ev := event.GetHttp().Event.(type) {
http := event.GetHttp()
http_event := http.Event
switch ev := http_event.(type) {
case *common.TapEvent_Http_RequestInit_:
return fmt.Sprintf("req id=%d:%d %s :method=%s :authority=%s :path=%s",
ev.RequestInit.Id.Base,
Expand Down
Loading

0 comments on commit c49c7e7

Please sign in to comment.